2020-07-31 11:31:32 +08:00
|
|
|
//===============================================================================
|
|
|
|
// Copyright (c) 2007-2016 Advanced Micro Devices, Inc. All rights reserved.
|
|
|
|
// Copyright (c) 2004-2006 ATI Technologies Inc.
|
|
|
|
//===============================================================================
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files(the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions :
|
2021-09-08 10:54:22 +08:00
|
|
|
//
|
2020-07-31 11:31:32 +08:00
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
2021-09-08 10:54:22 +08:00
|
|
|
//
|
2020-07-31 11:31:32 +08:00
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
// THE SOFTWARE.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <assert.h>
|
2021-09-08 10:54:22 +08:00
|
|
|
#include "common.h"
|
2020-07-31 11:31:32 +08:00
|
|
|
#include "3dquant_constants.h"
|
|
|
|
#include "3dquant_vpc.h"
|
2021-09-08 10:54:22 +08:00
|
|
|
#include "bc7_definitions.h"
|
2020-07-31 11:31:32 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef BC7_DEBUG_TO_RESULTS_TXT
|
|
|
|
FILE *fp;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define EPSILON 0.000001
|
|
|
|
#define MAX_TRY 20
|
|
|
|
#undef TRACE
|
|
|
|
|
|
|
|
#define MAX_TRACE 250000
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
struct TRACE {
|
|
|
|
int k;
|
|
|
|
double d;
|
2020-07-31 11:31:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int trcnts[MAX_CLUSTERS][MAX_ENTRIES_QUANT_TRACE];
|
|
|
|
|
|
|
|
#define USE_TRACE_WITH_DYNAMIC_MEM
|
|
|
|
|
|
|
|
#ifdef USE_TRACE_WITH_DYNAMIC_MEM
|
2021-09-08 10:54:22 +08:00
|
|
|
int* amd_codes[MAX_CLUSTERS][MAX_ENTRIES_QUANT_TRACE] = {};
|
|
|
|
TRACE* amd_trs[MAX_CLUSTERS][MAX_ENTRIES_QUANT_TRACE] = {};
|
2020-07-31 11:31:32 +08:00
|
|
|
#else
|
2021-09-08 10:54:22 +08:00
|
|
|
int amd_codes[MAX_CLUSTERS][MAX_ENTRIES_QUANT_TRACE][MAX_TRACE];
|
|
|
|
TRACE amd_trs[MAX_CLUSTERS][MAX_ENTRIES_QUANT_TRACE][MAX_TRACE];
|
2020-07-31 11:31:32 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static int g_Quant_init = 0;
|
|
|
|
void traceBuilder (int numEntries, int numClusters,struct TRACE tr [], int code[], int *trcnt );
|
|
|
|
|
|
|
|
std::mutex mtx;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void Quant_Init(void) {
|
|
|
|
if (g_Quant_init > 0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
g_Quant_init++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (amd_codes[0][0]) return;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
mtx.lock();
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for ( int numClusters = 0; numClusters < MAX_CLUSTERS; numClusters++ ) {
|
|
|
|
for ( int numEntries = 0; numEntries < MAX_ENTRIES_QUANT_TRACE; numEntries++ ) {
|
|
|
|
#ifdef USE_TRACE_WITH_DYNAMIC_MEM
|
|
|
|
amd_codes[ numClusters][ numEntries ] = new int[ MAX_TRACE ];
|
|
|
|
amd_trs[ numClusters ][ numEntries ] = new TRACE[ MAX_TRACE ];
|
|
|
|
|
|
|
|
assert(amd_codes[ numClusters][ numEntries ]);
|
|
|
|
assert(amd_trs[ numClusters ][ numEntries ]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
traceBuilder ( numEntries+1,
|
|
|
|
numClusters+1,
|
2020-07-31 11:31:32 +08:00
|
|
|
amd_trs[numClusters][numEntries],
|
|
|
|
amd_codes[numClusters][numEntries],
|
2021-09-08 10:54:22 +08:00
|
|
|
trcnts[numClusters]+(numEntries));
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
init_ramps();
|
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
g_Quant_init++;
|
|
|
|
|
|
|
|
mtx.unlock();
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void Quant_DeInit(void) {
|
2023-09-22 23:22:04 +08:00
|
|
|
// gpuopen issue 242 quick fix. We are not freeing memory to improve BC7 compression performance
|
|
|
|
return;
|
|
|
|
|
|
|
|
// g_Quant_init--;
|
|
|
|
// if (g_Quant_init > 1) {
|
|
|
|
// return;
|
|
|
|
// } else {
|
|
|
|
// g_Quant_init = 0; // Reset in case user called Quant_DeInit too many times without matching Quant_Init
|
|
|
|
// if (amd_codes[0][0] == nullptr) return;
|
|
|
|
|
|
|
|
// #ifdef USE_TRACE_WITH_DYNAMIC_MEM
|
|
|
|
|
|
|
|
// for (int i = 0; i < MAX_CLUSTERS; i++) {
|
|
|
|
// for (int j = 0; j < MAX_ENTRIES_QUANT_TRACE; j++) {
|
|
|
|
// if (amd_codes[i][j]) {
|
|
|
|
// delete[] amd_codes[i][j];
|
|
|
|
// amd_codes[i][j] = nullptr;
|
|
|
|
// }
|
|
|
|
// if (amd_trs[i][j]) {
|
|
|
|
// delete[] amd_trs[i][j];
|
|
|
|
// amd_trs[i][j] = nullptr;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2023-09-22 23:22:04 +08:00
|
|
|
// #endif
|
|
|
|
// }
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================================================
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void sugar(void) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(("sugar!"))
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
// called many times Optimize this call!
|
2021-09-08 10:54:22 +08:00
|
|
|
inline int a_compare( const void *arg1, const void *arg2 ) {
|
2020-07-31 11:31:32 +08:00
|
|
|
// #ifdef USE_DBGTRACE
|
|
|
|
// DbgTrace(());
|
|
|
|
// #endif
|
|
|
|
if (((a* )arg1)->d-((a* )arg2)->d > 0 ) return 1;
|
|
|
|
if (((a* )arg1)->d-((a* )arg2)->d < 0 ) return -1;
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// We ignore the issue of ordering equal elements here, though it can affect results abit
|
|
|
|
//
|
2021-09-08 10:54:22 +08:00
|
|
|
void sortProjection(double projection[MAX_ENTRIES], int order[MAX_ENTRIES], int numEntries) {
|
2020-07-31 11:31:32 +08:00
|
|
|
int i;
|
|
|
|
a what[MAX_ENTRIES+MAX_PARTITIONS_TABLE];
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i < numEntries; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
what[what[i].i=i].d = projection[i];
|
|
|
|
|
|
|
|
qsort((void*)&what, numEntries, sizeof(a),a_compare);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < numEntries; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
order[i]=what[i].i;
|
|
|
|
};
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void covariance(double data[][DIMENSION], int numEntries, double cov[DIMENSION][DIMENSION]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int i,j,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<=i; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j]+=data[k][i]*data[k][j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=i+1; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j] = cov[j][i];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
void covariance_d(double data[][MAX_DIMENSION_BIG], int numEntries, double cov[MAX_DIMENSION_BIG][MAX_DIMENSION_BIG], int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++)
|
|
|
|
for(j=0; j<=i; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j]+=data[k][i]*data[k][j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<dimension; i++)
|
|
|
|
for(j=i+1; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[i][j] = cov[j][i];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void centerInPlace(double data[][DIMENSION], int numEntries, double mean[DIMENSION]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int i,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
mean[i]=0;
|
|
|
|
for(k=0; k<numEntries; k++)
|
|
|
|
mean[i]+=data[k][i];
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (!numEntries)
|
|
|
|
return;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
mean[i]/=(double) numEntries;
|
|
|
|
for(k=0; k<numEntries; k++)
|
|
|
|
data[k][i]-=mean[i];
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void centerInPlace_d(double data[][MAX_DIMENSION_BIG], int numEntries, double mean[MAX_DIMENSION_BIG], int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int i,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++) {
|
|
|
|
mean[i]=0;
|
|
|
|
for(k=0; k<numEntries; k++)
|
|
|
|
mean[i]+=data[k][i];
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!numEntries)
|
|
|
|
return;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
mean[i]/=(double) numEntries;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
data[k][i]-=mean[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void project(double data[][DIMENSION], int numEntries, double vector[DIMENSION], double projection[MAX_ENTRIES]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
// assume that vector is normalized already
|
|
|
|
int i,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
projection[k]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
projection[k]+=data[k][i]*vector[i];
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void project_d(double data[][MAX_DIMENSION_BIG], int numEntries, double vector[MAX_DIMENSION_BIG], double projection[MAX_ENTRIES], int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
// assume that vector is normalized already
|
|
|
|
int i,k;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
projection[k]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++) {
|
|
|
|
projection[k]+=data[k][i]*vector[i];
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void eigenVector(double cov[DIMENSION][DIMENSION], double vector[DIMENSION]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
// calculate an eigenvecto corresponding to a biggest eigenvalue
|
|
|
|
// will work for non-zero non-negative matricies only
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
#define EV_ITERATION_NUMBER 20
|
|
|
|
#define EV_SLACK 2 /* additive for exp base 2)*/
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
int i,j,k,l, m, n,p,q;
|
|
|
|
double c[2][DIMENSION][DIMENSION];
|
|
|
|
double maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
c[0][i][j] =cov[i][j];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
p = (int) floor(log( (DBL_MAX_EXP - EV_SLACK) / ceil (log((double)DIMENSION)/log(2.)) )/log(2.));
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
assert(p>0);
|
|
|
|
|
|
|
|
p = p >0 ? p : 1;
|
|
|
|
|
|
|
|
q = (EV_ITERATION_NUMBER+p-1) / p;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
l=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(n=0; n<q; n++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
maxDiag = 0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
maxDiag = c[l][i][i] > maxDiag ? c[l][i][i] : maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (maxDiag<=0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
sugar();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(maxDiag > 0);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
c[l][i][j] /=maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(m=0; m<p; m++) {
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
c[1-l][i][j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<DIMENSION; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
c[1-l][i][j]+=c[l][i][k]*c[l][k][j];
|
|
|
|
}
|
|
|
|
l=1-l;
|
|
|
|
}
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
maxDiag = 0;
|
|
|
|
k =0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
k = c[l][i][i] > maxDiag ? i : k;
|
|
|
|
maxDiag = c[l][i][i] > maxDiag ? c[l][i][i] : maxDiag;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
double t;
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
t+=c[l][k][i]*c[l][k][i];
|
|
|
|
vector[i]=c[l][k][i];
|
|
|
|
}
|
|
|
|
// normalization is really optional
|
|
|
|
t= sqrt(t);
|
|
|
|
assert(t>0);
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t<=0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
sugar();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
vector[i]/=t;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void eigenVector_d(double cov[MAX_DIMENSION_BIG][MAX_DIMENSION_BIG], double vector[MAX_DIMENSION_BIG], int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// calculate an eigenvecto corresponding to a biggest eigenvalue
|
|
|
|
// will work for non-zero non-negative matricies only
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
#define EV_ITERATION_NUMBER 20
|
|
|
|
#define EV_SLACK 2 /* additive for exp base 2)*/
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
int i,j,k,l, m, n,p,q;
|
|
|
|
double c[2][MAX_DIMENSION_BIG][MAX_DIMENSION_BIG];
|
|
|
|
double maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++)
|
|
|
|
for(j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
c[0][i][j] =cov[i][j];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
p = (int) floor(log( (DBL_MAX_EXP - EV_SLACK) / ceil (log((double)dimension)/log(2.)) )/log(2.));
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
assert(p>0);
|
|
|
|
|
|
|
|
p = p >0 ? p : 1;
|
|
|
|
|
|
|
|
q = (EV_ITERATION_NUMBER+p-1) / p;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
l=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(n=0; n<q; n++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
maxDiag = 0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
maxDiag = c[l][i][i] > maxDiag ? c[l][i][i] : maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (maxDiag<=0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
sugar();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(maxDiag >0);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<dimension; i++)
|
|
|
|
for(j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
c[l][i][j] /=maxDiag;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(m=0; m<p; m++) {
|
|
|
|
for(i=0; i<dimension; i++)
|
|
|
|
for(j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
double temp=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<dimension; k++) {
|
|
|
|
// Notes:
|
2020-07-31 11:31:32 +08:00
|
|
|
// This is the most consuming portion of the code and needs optimizing for perfromance
|
|
|
|
temp += c[l][i][k]*c[l][k][j];
|
2021-09-08 10:54:22 +08:00
|
|
|
}
|
|
|
|
c[1-l][i][j]=temp;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
l=1-l;
|
|
|
|
}
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
maxDiag = 0;
|
|
|
|
k =0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++) {
|
|
|
|
k = c[l][i][i] > maxDiag ? i : k;
|
|
|
|
maxDiag = c[l][i][i] > maxDiag ? c[l][i][i] : maxDiag;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
double t;
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<dimension; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
t+=c[l][k][i]*c[l][k][i];
|
|
|
|
vector[i]=c[l][k][i];
|
|
|
|
}
|
|
|
|
// normalization is really optional
|
|
|
|
t= sqrt(t);
|
|
|
|
assert(t>0);
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t<=0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
sugar();
|
|
|
|
return;
|
2021-09-08 10:54:22 +08:00
|
|
|
}
|
|
|
|
for(i=0; i<dimension; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
vector[i]/=t;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
double partition2(double data[][DIMENSION], int numEntries,int index[]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(("-> get_partition_subset() is not implemented data is global"));
|
|
|
|
#endif
|
|
|
|
int i,j,k;
|
|
|
|
double cov[2][DIMENSION][DIMENSION];
|
|
|
|
double center[2][DIMENSION];
|
2021-09-08 10:54:22 +08:00
|
|
|
double cnt[2] = {0,0};
|
2020-07-31 11:31:32 +08:00
|
|
|
double vector[2][DIMENSION];
|
|
|
|
double acc=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cnt[index[k]]++;
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
center[0][i]=center[1][i]=0;
|
|
|
|
for(k=0; k<numEntries; k++)
|
|
|
|
center[index[k]][i]+=data[k][i];
|
|
|
|
}
|
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<=i; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[0][i][j]=cov[1][i][j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[index[k]][i][j]+=data[k][i]*data[k][j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<=i; j++)
|
|
|
|
for (k=0; k<2; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
if (cnt[k]!=0)
|
|
|
|
cov[k][i][j] -=center[k][i]*center[k][j]/(double)cnt[k];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=i+1; j<DIMENSION; j++)
|
|
|
|
for(k=0; k<2; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
cov[k][i][j] = cov[k][j][i];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<2; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
eigenVector(cov[k], vector[k]); // assume the returned vector is nomalized
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(k=0; k<2; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
acc+=cov[k][i][i];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<DIMENSION; j++)
|
|
|
|
for(k=0; k<2; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
acc-=cov[k][i][j]*vector[k][i]*vector[k][j];
|
|
|
|
|
|
|
|
return(acc);
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
void quantEven(double data[MAX_ENTRIES][DIMENSION],int numEntries, int numClusters, int index[MAX_ENTRIES]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Data should be centered, otherwise will not work
|
|
|
|
// The running time (number of iteration of the external loop) is
|
|
|
|
// binomial(numEntries+numClusters-2, numClusters-1)
|
|
|
|
// First cluster is always used, (without loss of generality)
|
|
|
|
// Ramp should be shifted such, that the first element ramp[0] is 0
|
|
|
|
int i,k;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
int level;
|
|
|
|
|
|
|
|
double t,s;
|
|
|
|
int c =1;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
int cluster[MAX_CLUSTERS];
|
|
|
|
|
|
|
|
int bestCluster[MAX_CLUSTERS];
|
|
|
|
// stores the las index for the cluster
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double dpAcc [MAX_CLUSTERS][DIMENSION];
|
|
|
|
double index2Acc [MAX_CLUSTERS]; // for backtraking
|
|
|
|
double indexAcc [MAX_CLUSTERS];
|
|
|
|
|
|
|
|
double dRamp2[MAX_CLUSTERS]; // first differenses of the (shifted) ramp squared
|
|
|
|
|
|
|
|
double S;
|
|
|
|
|
|
|
|
double nErrorNum=0; // not the actual error, but some (decreasing) linear functional of it represented
|
2021-09-08 10:54:22 +08:00
|
|
|
// as numerator and denominator
|
|
|
|
double nErrorDen=1;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
level=1;
|
|
|
|
|
|
|
|
bestCluster[0]=cluster[0]=cluster[1]=numEntries;
|
|
|
|
|
|
|
|
|
|
|
|
indexAcc[0]=index2Acc[0]=indexAcc[1]=index2Acc[1]=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
dpAcc[0][i]=dpAcc[1][i]=0;
|
|
|
|
|
|
|
|
S = 1/sqrt((double) numEntries);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=1; i<MAX_CLUSTERS; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
dRamp2[i] = 2*i-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
level=1;
|
|
|
|
|
|
|
|
do {
|
2021-09-08 10:54:22 +08:00
|
|
|
k = --cluster[level-1];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
indexAcc [level] += S;
|
|
|
|
index2Acc [level] += dRamp2 [level];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
t=0;
|
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
// using scaled ramp instead of non-scaled here effectively scales the data, so
|
|
|
|
// the resulting quantisation will be the same, but the error metric value will be different
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
dpAcc [level][i] += data[k][i];
|
|
|
|
t += dpAcc[level][i] * dpAcc[level][i];
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if ((cluster[level]!= numEntries || cluster[level-1]!=0) &&
|
2020-07-31 11:31:32 +08:00
|
|
|
nErrorNum * (s=index2Acc[level]-indexAcc[level] * indexAcc[level]) < nErrorDen * t) {
|
2021-09-08 10:54:22 +08:00
|
|
|
nErrorNum=t;
|
|
|
|
nErrorDen=s;
|
|
|
|
for(i=0; i<=level; i++)
|
|
|
|
bestCluster[i]=cluster[i];
|
|
|
|
}
|
|
|
|
c++;
|
|
|
|
|
|
|
|
if (level < numClusters - 1 ) {
|
|
|
|
// go up
|
|
|
|
level++;
|
|
|
|
indexAcc [level]=indexAcc [level-1];
|
|
|
|
index2Acc[level]=index2Acc[level-1];
|
|
|
|
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
dpAcc [level][i]=dpAcc [level-1][i];
|
|
|
|
|
|
|
|
} else while ((level-1) && cluster[level-1]==cluster[level-2])
|
2020-07-31 11:31:32 +08:00
|
|
|
level--;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
cluster[level]=numEntries;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
} while (level != 1 || cluster[level-1] != 0);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (level=i=0; i< numEntries; i++) {
|
|
|
|
while (i==bestCluster[level])
|
|
|
|
level++;
|
2020-07-31 11:31:32 +08:00
|
|
|
index[i]=level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void quantLineConstr(double data[][DIMENSION], int order[MAX_ENTRIES],int numEntries, int numClusters, int index[MAX_ENTRIES]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Data should be centered, otherwise will not work
|
|
|
|
// The running time (number of iteration of the external loop) is
|
|
|
|
// binomial(numEntries+numClusters-2, numClusters-1)
|
|
|
|
// Index just defines which points should be combined in a cluster
|
|
|
|
int i,j,k;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
int level;
|
|
|
|
|
|
|
|
double t,s;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
// We need paddingof 0 on -1 index
|
2021-09-08 10:54:22 +08:00
|
|
|
int cluster_[MAX_CLUSTERS+1]= {0};
|
2020-07-31 11:31:32 +08:00
|
|
|
int *cluster = cluster_+1;
|
|
|
|
|
|
|
|
int bestCluster[MAX_CLUSTERS];
|
|
|
|
// stores the las index for the cluster
|
|
|
|
|
|
|
|
double cov[DIMENSION][DIMENSION];
|
|
|
|
double dir[DIMENSION];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
double gcAcc[MAX_CLUSTERS][DIMENSION];// Clusters' graviti centers
|
|
|
|
double gcSAcc[MAX_CLUSTERS][DIMENSION];// Clusters' graviti centers
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
double nError=0; // not the actual error, but some (decreasing) linear functional of it represented
|
2021-09-08 10:54:22 +08:00
|
|
|
// as numerator and denominator
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
level=1;
|
|
|
|
|
|
|
|
|
|
|
|
bestCluster[0]=cluster[0]=cluster[1]=numEntries;
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
gcAcc[0][i]=gcAcc[1][i]=0;
|
|
|
|
|
|
|
|
|
|
|
|
level=1;
|
|
|
|
|
|
|
|
do {
|
2021-09-08 10:54:22 +08:00
|
|
|
assert(level >0);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
k = order[--cluster[level-1]];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
s=(cluster[level-1]-cluster[level-2]) == 0 ? 0: 1/sqrt( (double) (cluster[level-1]-cluster[level-2])); // see cluster_ decl for
|
|
|
|
// cluster[-1] value
|
|
|
|
t=1/sqrt((double) (numEntries-cluster[level-1]));
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++) {
|
|
|
|
gcAcc[level ][i] += data[k][i];
|
|
|
|
gcAcc[level-1][i] -= data[k][i];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
gcSAcc[level-1][i] = gcAcc[level-1][i] * s;
|
|
|
|
gcSAcc[level ][i] = gcAcc[level ][i] * t;
|
|
|
|
}
|
|
|
|
covariance(gcSAcc, level+1, cov);
|
|
|
|
eigenVector(cov, dir);
|
|
|
|
// assume the vector is normalized here
|
|
|
|
t=0;
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
for(j=0; j<DIMENSION; j++)
|
|
|
|
t+= cov[i][j]*dir[i]*dir[j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t>nError) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
nError=t;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<=level; i++)
|
|
|
|
bestCluster[i]=cluster[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (level < numClusters - 1 ) {
|
|
|
|
// go up
|
|
|
|
level++;
|
|
|
|
for(i=0; i<DIMENSION; i++)
|
|
|
|
gcAcc [level][i]=0;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
} else while ((level-1) && cluster[level-1]==cluster[level-2]) {
|
2020-07-31 11:31:32 +08:00
|
|
|
level--;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<DIMENSION; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
gcAcc [level][i]+=gcAcc [level+1][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
cluster[level]=numEntries;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
} while (level != 1 || cluster[level-1] != 1);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (level=i=0; i< numEntries; i++) {
|
|
|
|
while (i==bestCluster[level])
|
|
|
|
level++;
|
2020-07-31 11:31:32 +08:00
|
|
|
index[order[i]]=level;
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
double totalError(double data[MAX_ENTRIES][DIMENSION],double data2[MAX_ENTRIES][DIMENSION],int numEntries) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int i,j;
|
|
|
|
double t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
t+= (data[i][j]-data2[i][j])*(data[i][j]-data2[i][j]);
|
2020-07-31 11:31:32 +08:00
|
|
|
return t;
|
|
|
|
};
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
double totalError_d(double data[MAX_ENTRIES][MAX_DIMENSION_BIG],double data2[MAX_ENTRIES][MAX_DIMENSION_BIG],int numEntries, int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
int i,j;
|
|
|
|
double t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<dimension; j++)
|
|
|
|
t+= (data[i][j]-data2[i][j])*(data[i][j]-data2[i][j]);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(( "[%3.3f]",t));
|
|
|
|
#endif
|
|
|
|
return t;
|
|
|
|
};
|
|
|
|
|
|
|
|
double optQuantEven(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][DIMENSION],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index[MAX_ENTRIES],
|
|
|
|
double out[MAX_ENTRIES][DIMENSION],
|
|
|
|
double direction [DIMENSION],double *step
|
2021-09-08 10:54:22 +08:00
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int maxTry=MAX_TRY;
|
|
|
|
int i,j,k;
|
|
|
|
double t,s;
|
|
|
|
double centered[MAX_ENTRIES][DIMENSION];
|
|
|
|
double ordered[MAX_ENTRIES][DIMENSION];
|
|
|
|
double mean[DIMENSION];
|
|
|
|
double cov[DIMENSION][DIMENSION];
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int order[MAX_ENTRIES];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace(centered, numEntries, mean);
|
|
|
|
covariance(centered, numEntries, cov);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t==0 || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector(cov, direction);
|
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (i) {
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
2020-07-31 11:31:32 +08:00
|
|
|
t+=direction[j]*direction[j];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// Actually we don't need to normailize direction here, as the
|
2020-07-31 11:31:32 +08:00
|
|
|
// optimal quntization (index) is invariant of the scale.
|
|
|
|
// Hence we don't care about possible degenration of the <direction> either
|
|
|
|
// though normally it should not happen
|
|
|
|
|
|
|
|
// However, the EPSILON should be scaled, otherwise is does not make sense
|
|
|
|
|
|
|
|
t = sqrt(t)*EPSILON;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=1; j < numEntries; j++)
|
|
|
|
if (projected[order[j]] < projected[order[j-1]]-t /*EPSILON*/)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (j >= numEntries)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortProjection(projected, order, numEntries);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
ordered[k][j]=centered[order[k]][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
quantEven(ordered, numEntries, numClusters, index);
|
|
|
|
|
|
|
|
}
|
|
|
|
s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double q=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
2021-09-08 10:54:22 +08:00
|
|
|
q+= direction[j]* direction[j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t==0)
|
2020-07-31 11:31:32 +08:00
|
|
|
DbgTrace(("l;lkjk"));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
assert(t !=0);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
out[order[i]][j]=mean[j]+direction[j]*t*(index[i]-s);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
// normalize direction for output
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
q=sqrt(q);
|
|
|
|
*step=t*q;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
|
|
|
return totalError(data,out,numEntries);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int requantize(double data[MAX_ENTRIES][DIMENSION],
|
2021-09-08 10:54:22 +08:00
|
|
|
double centers[MAX_CLUSTERS][DIMENSION], int numEntries, int numClusters,int index[MAX_ENTRIES] ) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
double p,q;
|
|
|
|
int cnt[MAX_CLUSTERS];
|
|
|
|
int change =0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
p=0;
|
|
|
|
index[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<DIMENSION; k++)
|
|
|
|
p+=(data[i][k]-centers[index[i]][k])*(data[i][k]-centers[index[i]][k]);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(j=0; j<numClusters; j++) {
|
|
|
|
q=0;
|
|
|
|
for(k=0; k<DIMENSION; k++)
|
|
|
|
q+=(data[i][k]-centers[j][k])*(data[i][k]-centers[j][k]);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
change |= q < p ? (j!= index[i]) : 0;
|
|
|
|
index[i]= q < p ? j : index[i];
|
|
|
|
p = q < p ? q : p;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(j=0; j<numClusters; j++)
|
|
|
|
cnt[j]=0;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(j=0; j<numClusters; j++)
|
|
|
|
for(k=0; k<DIMENSION; k++)
|
|
|
|
centers[j][k]=0;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
cnt[index[i]]++;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(k=0; k<DIMENSION; k++)
|
|
|
|
centers[index[i]][k]+=data[i][k];
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
for(j=0; j<numClusters; j++)
|
|
|
|
for(k=0; k<DIMENSION; k++)
|
|
|
|
centers[j][k]/=(double) cnt[j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
return(change);
|
|
|
|
}
|
|
|
|
|
|
|
|
double optQuantLineConstr(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][DIMENSION],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index[MAX_ENTRIES],
|
2021-09-08 10:54:22 +08:00
|
|
|
double out[MAX_ENTRIES][DIMENSION]
|
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int maxTry=MAX_TRY;
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
double t;
|
|
|
|
|
|
|
|
double centered[MAX_ENTRIES][DIMENSION];
|
|
|
|
|
|
|
|
double mean[DIMENSION];
|
|
|
|
|
|
|
|
double cov[DIMENSION][DIMENSION];
|
|
|
|
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
|
|
|
|
double direction [DIMENSION];
|
|
|
|
|
|
|
|
int order[MAX_ENTRIES];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace(centered, numEntries, mean);
|
|
|
|
covariance(centered, numEntries, cov);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t==0 || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector(cov, direction);
|
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (i) {
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=centered[k][j]*index[k];
|
|
|
|
t=direction[j]*direction[j];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// Actually we don't need to normailize direction here, as the
|
2020-07-31 11:31:32 +08:00
|
|
|
// optimal quntization (index) is invariant of the scale.
|
|
|
|
// Hence we don't care about possible degenration of the <direction> either
|
|
|
|
// though normally it should not happen
|
|
|
|
|
|
|
|
// However, the EPSILON should be scaled, otherwise is does not make sense
|
|
|
|
|
|
|
|
t = sqrt(t)*EPSILON;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=1; j < numEntries; j++)
|
|
|
|
if (projected[order[j]] < projected[order[j-1]]-t /*EPSILON*/)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (j >= numEntries)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortProjection(projected, order, numEntries);
|
|
|
|
|
|
|
|
quantLineConstr(centered, order, numEntries, numClusters, index);
|
|
|
|
|
|
|
|
}
|
|
|
|
double gcAcc[MAX_CLUSTERS][DIMENSION];
|
|
|
|
double gcSAcc[MAX_CLUSTERS][DIMENSION];
|
|
|
|
double gcS[MAX_CLUSTERS];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<MAX_CLUSTERS; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
gcS[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for(j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
gcAcc[i][j]=0;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
gcS[index[k]]+=1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
gcAcc[index[k]][j]+=centered[k][j];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<numClusters; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
if (gcS[i]!=0) {
|
|
|
|
gcSAcc[i][j] = gcAcc[i][j]/sqrt((double)gcS[i]);
|
|
|
|
gcAcc[i][j] /= ((double)gcS[i]);
|
2021-09-08 10:54:22 +08:00
|
|
|
} else
|
2020-07-31 11:31:32 +08:00
|
|
|
gcSAcc[i][j] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
covariance(gcSAcc, numClusters, cov);
|
|
|
|
eigenVector(cov, direction);
|
|
|
|
// assume the vector is normalized here
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for(i=0; i<numClusters; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
gcS[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
gcS[i]+=direction[j]*gcAcc[i][j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
out[i][j]=mean[j]+direction[j]*gcS[index[i]];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
return totalError(data,out,numEntries);
|
|
|
|
};
|
|
|
|
|
|
|
|
void quantTrace(double data[MAX_ENTRIES_QUANT_TRACE][DIMENSION],int numEntries, int numClusters, int index[MAX_ENTRIES_QUANT_TRACE]) {
|
|
|
|
// Data should be centered, otherwise will not work
|
|
|
|
int i,j,k;
|
|
|
|
double sdata[2*MAX_ENTRIES][DIMENSION];
|
|
|
|
double dpAcc [DIMENSION];
|
|
|
|
double M =0;
|
|
|
|
struct TRACE *tr ;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
tr=amd_trs[numClusters-1][numEntries-1];
|
|
|
|
|
|
|
|
int trcnt =trcnts[numClusters-1][numEntries-1];
|
|
|
|
|
|
|
|
int *code;
|
2021-09-08 10:54:22 +08:00
|
|
|
code=amd_codes[numClusters-1][numEntries-1];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++) {
|
|
|
|
sdata[2*i][j]= data[i][j];
|
|
|
|
sdata[2*i+1][j]=-data[i][j];
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
dpAcc[j]=0;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
k=-1;
|
|
|
|
|
|
|
|
#define UROLL_STEP(i) \
|
|
|
|
dpAcc[0]+=sdata[tr[i].k][0];\
|
|
|
|
dpAcc[1]+=sdata[tr[i].k][1];\
|
|
|
|
dpAcc[2]+=sdata[tr[i].k][2];\
|
|
|
|
{ double c; \
|
|
|
|
c = (dpAcc[0]*dpAcc[0]+dpAcc[1]*dpAcc[1]+dpAcc[2]*dpAcc[2])*tr[i].d;\
|
|
|
|
if (c > M) {k=i;M=c;};};
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i+15<trcnt; i+=16) {
|
|
|
|
UROLL_STEP(i)
|
|
|
|
UROLL_STEP(i+1)
|
|
|
|
UROLL_STEP(i+2)
|
|
|
|
UROLL_STEP(i+3)
|
|
|
|
UROLL_STEP(i+4)
|
|
|
|
UROLL_STEP(i+5)
|
|
|
|
UROLL_STEP(i+6)
|
|
|
|
UROLL_STEP(i+7)
|
|
|
|
UROLL_STEP(i+8)
|
|
|
|
UROLL_STEP(i+9)
|
|
|
|
UROLL_STEP(i+10)
|
|
|
|
UROLL_STEP(i+11)
|
|
|
|
UROLL_STEP(i+12)
|
|
|
|
UROLL_STEP(i+13)
|
|
|
|
UROLL_STEP(i+14)
|
|
|
|
UROLL_STEP(i+15)
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (; i<trcnt; i++) {
|
|
|
|
UROLL_STEP(i)
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((k<0)||(k >=MAX_TRACE)) { // NP
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
k = code[k];
|
|
|
|
i=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<numEntries; j++) {
|
|
|
|
while ((k & 1) ==0) {
|
|
|
|
i++;
|
|
|
|
k>>=1;
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
index[j]=i;
|
2021-09-08 10:54:22 +08:00
|
|
|
k>>=1;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void quantTrace_d(double data[MAX_ENTRIES_QUANT_TRACE][MAX_DIMENSION_BIG],int numEntries, int numClusters, int index[MAX_ENTRIES_QUANT_TRACE],int dimension) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
2021-09-08 10:54:22 +08:00
|
|
|
// Data should be centered, otherwise will not work
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
int i,j,k;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double sdata[2*MAX_ENTRIES][MAX_DIMENSION_BIG];
|
|
|
|
|
|
|
|
double dpAcc [MAX_DIMENSION_BIG];
|
|
|
|
|
|
|
|
double M =0;
|
|
|
|
|
|
|
|
struct TRACE *tr ;
|
|
|
|
tr=amd_trs[numClusters-1][numEntries-1];
|
|
|
|
|
|
|
|
int trcnt =trcnts[numClusters-1][numEntries-1];
|
|
|
|
|
|
|
|
int *code;
|
2021-09-08 10:54:22 +08:00
|
|
|
code=amd_codes[numClusters-1][numEntries-1];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
sdata[2*i][j]= data[i][j];
|
|
|
|
sdata[2*i+1][j]=-data[i][j];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
dpAcc[j]=0;
|
|
|
|
|
|
|
|
k=-1;
|
|
|
|
|
|
|
|
#define UROLL_STEP_1(i) \
|
|
|
|
dpAcc[0]+=sdata[tr[i].k][0];\
|
|
|
|
{\
|
|
|
|
double c; \
|
|
|
|
c = (dpAcc[0]*dpAcc[0])*tr[i].d;\
|
|
|
|
if (c > M) {k=i;M=c;};\
|
|
|
|
};
|
|
|
|
|
|
|
|
#define UROLL_STEP_2(i) \
|
|
|
|
dpAcc[0]+=sdata[tr[i].k][0];\
|
|
|
|
dpAcc[1]+=sdata[tr[i].k][1];\
|
|
|
|
{ double c; \
|
|
|
|
c = (dpAcc[0]*dpAcc[0]+dpAcc[1]*dpAcc[1])*tr[i].d;\
|
|
|
|
if (c > M) {k=i;M=c;};};
|
|
|
|
|
|
|
|
#define UROLL_STEP_3(i) \
|
|
|
|
dpAcc[0]+=sdata[tr[i].k][0];\
|
|
|
|
dpAcc[1]+=sdata[tr[i].k][1];\
|
|
|
|
dpAcc[2]+=sdata[tr[i].k][2];\
|
|
|
|
{ double c; \
|
|
|
|
c = (dpAcc[0]*dpAcc[0]+dpAcc[1]*dpAcc[1]+dpAcc[2]*dpAcc[2])*tr[i].d;\
|
|
|
|
if (c > M) {k=i;M=c;};};
|
|
|
|
|
|
|
|
#define UROLL_STEP_4(i) \
|
|
|
|
dpAcc[0]+=sdata[tr[i].k][0];\
|
|
|
|
dpAcc[1]+=sdata[tr[i].k][1];\
|
|
|
|
dpAcc[2]+=sdata[tr[i].k][2];\
|
|
|
|
dpAcc[3]+=sdata[tr[i].k][3];\
|
|
|
|
{ double c; \
|
|
|
|
c = (dpAcc[0]*dpAcc[0]+dpAcc[1]*dpAcc[1]+dpAcc[2]*dpAcc[2]+dpAcc[3]*dpAcc[3])*tr[i].d;\
|
|
|
|
if (c > M) {k=i;M=c;};};
|
|
|
|
|
|
|
|
#undef UROLL_STEP
|
|
|
|
|
|
|
|
#define UROLL_MACRO(UROLL_STEP){\
|
|
|
|
\
|
|
|
|
\
|
|
|
|
for (i=0;i+15<trcnt;i+=16)\
|
|
|
|
{\
|
|
|
|
UROLL_STEP(i)\
|
|
|
|
UROLL_STEP(i+1)\
|
|
|
|
UROLL_STEP(i+2)\
|
|
|
|
UROLL_STEP(i+3)\
|
|
|
|
UROLL_STEP(i+4)\
|
|
|
|
UROLL_STEP(i+5)\
|
|
|
|
UROLL_STEP(i+6)\
|
|
|
|
UROLL_STEP(i+7)\
|
|
|
|
UROLL_STEP(i+8)\
|
|
|
|
UROLL_STEP(i+9)\
|
|
|
|
UROLL_STEP(i+10)\
|
|
|
|
UROLL_STEP(i+11)\
|
|
|
|
UROLL_STEP(i+12)\
|
|
|
|
UROLL_STEP(i+13)\
|
|
|
|
UROLL_STEP(i+14)\
|
|
|
|
UROLL_STEP(i+15)\
|
|
|
|
}\
|
|
|
|
\
|
|
|
|
for (;i<trcnt;i++) {\
|
|
|
|
UROLL_STEP(i)\
|
|
|
|
}};
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
switch(dimension) {
|
|
|
|
case 1:
|
|
|
|
UROLL_MACRO(UROLL_STEP_1);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
UROLL_MACRO(UROLL_STEP_2);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
UROLL_MACRO(UROLL_STEP_3);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
UROLL_MACRO(UROLL_STEP_4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
break;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (k<0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(("ERROR: quatnTrace\n"));
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
k = code[k];
|
|
|
|
i=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<numEntries; j++) {
|
|
|
|
while ((k & 1) ==0) {
|
2020-07-31 11:31:32 +08:00
|
|
|
i++;
|
|
|
|
k>>=1;
|
|
|
|
}
|
|
|
|
index[j]=i;
|
|
|
|
|
|
|
|
k>>=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void quant_AnD_Shell(double* v_, int k, int n, int *idx) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
// input:
|
|
|
|
//
|
|
|
|
// v_ points, might be uncentered
|
|
|
|
// k - number of points in the ramp
|
|
|
|
// n - number of points in v_
|
|
|
|
//
|
|
|
|
// output:
|
|
|
|
//
|
|
|
|
// index, uncentered, in the range 0..k-1
|
|
|
|
//
|
2021-09-08 10:54:22 +08:00
|
|
|
#define MAX_BLOCK MAX_ENTRIES
|
2020-07-31 11:31:32 +08:00
|
|
|
int i,j;
|
|
|
|
double v[MAX_BLOCK];
|
|
|
|
double z[MAX_BLOCK];
|
|
|
|
a d[MAX_BLOCK];
|
|
|
|
double l;
|
|
|
|
double mm;
|
|
|
|
double r=0;
|
|
|
|
int mi;
|
|
|
|
|
|
|
|
assert((v_ != NULL) && (n>1) && (k>1));
|
|
|
|
|
|
|
|
double m, M, s, dm=0.;
|
2021-09-08 10:54:22 +08:00
|
|
|
m=M=v_[0];
|
|
|
|
|
|
|
|
for (i=1; i < n; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
m = m < v_[i] ? m : v_[i];
|
|
|
|
M = M > v_[i] ? M : v_[i];
|
|
|
|
}
|
|
|
|
if (M==m) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
idx[i]=0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(M-m >0);
|
|
|
|
s = (k-1)/(M-m);
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < n; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
v[i] = v_[i]*s;
|
|
|
|
|
|
|
|
idx[i]=(int)(z[i] = floor(v[i] +0.5 /* stabilizer*/ - m *s));
|
|
|
|
|
|
|
|
d[i].d = v[i]-z[i]- m *s;
|
2021-09-08 10:54:22 +08:00
|
|
|
d[i].i = i;
|
2020-07-31 11:31:32 +08:00
|
|
|
dm+= d[i].d;
|
|
|
|
r += d[i].d*d[i].d;
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
if (n*r- dm*dm >= (double)(n-1)/4 /*slack*/ /2) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
dm /= (double)n;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
d[i].d -= dm;
|
|
|
|
|
|
|
|
qsort((void*)&d, n, sizeof(a),a_compare);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// got into fundamental simplex
|
|
|
|
// move coordinate system origin to its center
|
|
|
|
for (i=0; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
d[i].d -= (2.*(double)i+1-(double)n)/2./(double)n;
|
|
|
|
|
|
|
|
mm=l=0.;
|
|
|
|
j=-1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < n; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
l+=d[i].d;
|
|
|
|
if (l < mm) {
|
|
|
|
mm =l;
|
|
|
|
j=i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// position which should be in 0
|
2020-07-31 11:31:32 +08:00
|
|
|
j = ++j % n;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=j; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
idx[d[i].i]++;
|
|
|
|
}
|
|
|
|
// get rid of an offset in idx
|
|
|
|
mi=idx[0];
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=1; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
mi = mi < idx[i]? mi :idx[i];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i < n; i++)
|
2020-07-31 11:31:32 +08:00
|
|
|
idx[i]-=mi;
|
|
|
|
}
|
|
|
|
|
|
|
|
double optQuantTrace(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][DIMENSION],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index_[MAX_ENTRIES],
|
|
|
|
double out[MAX_ENTRIES][DIMENSION],
|
|
|
|
double direction [DIMENSION],double *step
|
2021-09-08 10:54:22 +08:00
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int index[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int maxTry=MAX_TRY;
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
double t,s;
|
|
|
|
|
|
|
|
double centered[MAX_ENTRIES][DIMENSION];
|
|
|
|
|
|
|
|
double ordered[MAX_ENTRIES][DIMENSION];
|
|
|
|
|
|
|
|
double mean[DIMENSION];
|
|
|
|
|
|
|
|
double cov[DIMENSION][DIMENSION];
|
|
|
|
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int order[MAX_ENTRIES];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace(centered, numEntries, mean);
|
|
|
|
covariance(centered, numEntries, cov);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t==0 || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index_[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector(cov, direction);
|
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (i) {
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
2020-07-31 11:31:32 +08:00
|
|
|
t+=direction[j]*direction[j];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// Actually we don't need to normailize direction here, as the
|
2020-07-31 11:31:32 +08:00
|
|
|
// optimal quntization (index) is invariant of the scale.
|
|
|
|
// Hence we don't care about possible degenration of the <direction> either
|
|
|
|
// though normally it should not happen
|
|
|
|
|
|
|
|
// However, the EPSILON should be scaled, otherwise is does not make sense
|
|
|
|
|
|
|
|
t = sqrt(t)*EPSILON;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=1; j < numEntries; j++)
|
|
|
|
if (projected[order[j]] < projected[order[j-1]]-t /*EPSILON*/)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (j >= numEntries)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortProjection(projected, order, numEntries);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
ordered[k][j]=centered[order[k]][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
quantTrace(ordered, numEntries, numClusters, index);
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double q=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
2021-09-08 10:54:22 +08:00
|
|
|
q+= direction[j]* direction[j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t==0)
|
2020-07-31 11:31:32 +08:00
|
|
|
DbgTrace(("l;lkjk"));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
assert(t !=0);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++) {
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
out[order[i]][j]=mean[j]+direction[j]*t*(index[i]-s);
|
|
|
|
index_[order[i]]=index[i];
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// normalize direction for output
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
q=sqrt(q);
|
|
|
|
*step=t*q;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
return totalError(data,out,numEntries);
|
|
|
|
}
|
|
|
|
|
|
|
|
double optQuantTrace_d(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][MAX_DIMENSION_BIG],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index_[MAX_ENTRIES],
|
|
|
|
double out[MAX_ENTRIES][MAX_DIMENSION_BIG],
|
|
|
|
double direction [MAX_DIMENSION_BIG],double *step,
|
|
|
|
int dimension
|
2021-09-08 10:54:22 +08:00
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int index[MAX_ENTRIES];
|
|
|
|
int maxTry=MAX_TRY;
|
|
|
|
int i,j,k;
|
|
|
|
double t,s;
|
|
|
|
double centered[MAX_ENTRIES][MAX_DIMENSION_BIG];
|
|
|
|
double ordered[MAX_ENTRIES][MAX_DIMENSION_BIG];
|
|
|
|
double mean[MAX_DIMENSION_BIG];
|
|
|
|
double cov[DIMENSION][MAX_DIMENSION_BIG];
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
int order[MAX_ENTRIES];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace_d(centered, numEntries, mean, dimension);
|
|
|
|
covariance_d(centered, numEntries, cov, dimension);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t<EPSILON || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index_[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector_d(cov, direction, dimension);
|
|
|
|
project_d(centered, numEntries, direction, projected, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
|
|
|
if (i) {
|
2020-07-31 11:31:32 +08:00
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
2020-07-31 11:31:32 +08:00
|
|
|
t+=direction[j]*direction[j];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// Actually we don't need to normailize direction here, as the
|
2020-07-31 11:31:32 +08:00
|
|
|
// optimal quntization (index) is invariant of the scale.
|
|
|
|
// Hence we don't care about possible degenration of the <direction> either
|
|
|
|
// though normally it should not happen
|
|
|
|
|
|
|
|
// However, the EPSILON should be scaled, otherwise is does not make sense
|
|
|
|
|
|
|
|
t = sqrt(t)*EPSILON;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project_d(centered, numEntries, direction, projected, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=1; j < numEntries; j++)
|
|
|
|
if (projected[order[j]] < projected[order[j-1]]-t /*EPSILON*/)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (j >= numEntries)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortProjection(projected, order, numEntries);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
ordered[k][j]=centered[order[k]][j];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
quantTrace_d(ordered, numEntries, numClusters, index, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double q=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=ordered[k][j]*index[k];
|
|
|
|
q+= direction[j]* direction[j];
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
assert(t !=0);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++) {
|
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[order[i]][j]=mean[j]+direction[j]*t*(index[i]-s);
|
|
|
|
index_[order[i]]=index[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// normalize direction for output
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
q=sqrt(q);
|
|
|
|
*step=t*q;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
return totalError_d(data,out,numEntries, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
void traceBuilder (int numEntries, int numClusters,struct TRACE tr [], int code[], int *trcnt ) {
|
2020-07-31 11:31:32 +08:00
|
|
|
//=================
|
2021-09-08 10:54:22 +08:00
|
|
|
#define DIG(J_IN,I,N,J_OUT,DIR,NC,NCC) \
|
2020-07-31 11:31:32 +08:00
|
|
|
for (I=J_IN;I<N || NC < NCC ;I++) { \
|
|
|
|
J_OUT = ((((J_IN) & 0x1)==DIR) ? I : N-1-(I-(J_IN))); \
|
|
|
|
|
|
|
|
//=================
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
int i[7];
|
|
|
|
int j[7];
|
|
|
|
int k[7]= {0,1,2,3,4,5,6};
|
2020-07-31 11:31:32 +08:00
|
|
|
int n;
|
|
|
|
int c =0;
|
|
|
|
int c0 =0;
|
|
|
|
int p;
|
2021-09-08 10:54:22 +08:00
|
|
|
int h[8]= {0,0,0,0, 0,0,0,0};
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (numClusters == 1) {
|
2020-07-31 11:31:32 +08:00
|
|
|
tr[c].k=0;
|
|
|
|
tr[c].d=0;
|
|
|
|
code[c]=0;
|
|
|
|
*trcnt=0;
|
|
|
|
return;
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
h[numClusters-1]=numEntries;
|
|
|
|
|
|
|
|
int q = numEntries*(numClusters-1);
|
|
|
|
int q2 = numEntries*(numClusters-1)*(numClusters-1);
|
|
|
|
|
|
|
|
n = numEntries + numClusters -2; // higest delimiter postion; all points start in highest cluster
|
|
|
|
|
|
|
|
int cd = -(1<< (numClusters-1));
|
|
|
|
|
|
|
|
DIG( 0,i[0],n,j[0],0,numClusters,2)
|
|
|
|
DIG(j[0]+1,i[1],n,j[1],1,numClusters,3)
|
|
|
|
DIG(j[1]+1,i[2],n,j[2],0,numClusters,4)
|
|
|
|
DIG(j[2]+1,i[3],n,j[3],1,numClusters,5)
|
|
|
|
DIG(j[3]+1,i[4],n,j[4],0,numClusters,6)
|
|
|
|
DIG(j[4]+1,i[5],n,j[5],1,numClusters,7)
|
|
|
|
DIG(j[5]+1,i[6],n,j[6],0,numClusters,8)
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
int rescan;
|
|
|
|
do {
|
|
|
|
rescan=0;
|
|
|
|
for (p=0; p<numClusters-1; p++) {
|
|
|
|
|
|
|
|
if (abs(j[p]-k[p]) >1 ) {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
DbgTrace(("Driving trace generation error"));
|
|
|
|
for (p=0; p<numClusters-1; p++)
|
|
|
|
DbgTrace(("%d %d %d",k[p],j[p],n));
|
2020-07-31 11:31:32 +08:00
|
|
|
#endif
|
2021-09-08 10:54:22 +08:00
|
|
|
return;
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
else if (j[p]-k[p]== 1 ) {
|
|
|
|
int ci= k[p]-p; // move it one cluster down "-"
|
|
|
|
int cn=p+1;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
h[cn]--;
|
|
|
|
h[cn-1]++;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (h[cn] < 0 || h[cn-1]>= numEntries) {
|
|
|
|
rescan =1;
|
|
|
|
h[cn]++;
|
|
|
|
h[cn-1]--;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
else {
|
|
|
|
|
|
|
|
q2+= -2*cn+1;
|
|
|
|
q--;
|
|
|
|
|
|
|
|
{
|
|
|
|
int i1,cc=0;
|
|
|
|
for(i1=0; i1<numClusters; i1++) cc += i1*i1*h[i1];
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
if (cc !=q2)
|
|
|
|
DbgTrace(("1 - q2 %d %d", cc,q2));
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
if (ci <0 || ci>=numEntries || cn <1 || cn >= numClusters || h[cn] < 0 || h[cn-1]>= numEntries)
|
|
|
|
DbgTrace(("tre1 %d %d %d %d %d %d",ci,cn,numEntries,numClusters,h[cn],h[cn-1]));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cd |= (1<<k[p]);
|
|
|
|
cd &= ~(1<<j[p]);
|
|
|
|
|
|
|
|
if (c < MAX_TRACE) { // NP
|
|
|
|
tr[c].k=2*ci+1;
|
|
|
|
tr[c].d=1./((double) q2 - (double) q*(double) q /(double) (numEntries));
|
|
|
|
code[c]=cd;
|
|
|
|
c++;
|
|
|
|
} else {
|
|
|
|
// What to do here?
|
|
|
|
tr[c].k=0;
|
|
|
|
tr[c].d=0;
|
|
|
|
code[c]=0;
|
|
|
|
*trcnt=0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
k[p]=j[p];
|
|
|
|
}
|
|
|
|
} else if (j[p]-k[p]==-1 ) {
|
|
|
|
int ci=j[p]-p; // move it up
|
2020-07-31 11:31:32 +08:00
|
|
|
int cn =p;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
h[cn]--;
|
|
|
|
h[cn+1]++;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (h[cn] < 0 || h[cn+1]>= numEntries) {
|
|
|
|
rescan =1;
|
|
|
|
h[cn]++;
|
|
|
|
h[cn+1]--;
|
|
|
|
} else {
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
q2+= 2*cn+1;
|
|
|
|
q++;
|
|
|
|
{
|
|
|
|
int i1,cc=0;
|
|
|
|
for(i1=0; i1<numClusters; i1++) cc += i1*i1*h[i1];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
if (cc !=q2)
|
|
|
|
DbgTrace(("2- q2 %d %d", cc,q2));
|
2020-07-31 11:31:32 +08:00
|
|
|
#endif
|
2021-09-08 10:54:22 +08:00
|
|
|
};
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
if (ci <0 || ci>=numEntries || cn >= numClusters-1 || h[cn] < 0 || h[cn+1]>= numEntries)
|
|
|
|
DbgTrace(("tre2 %d %d %d %d %d %d",ci,cn,numEntries,numClusters,h[cn],h[cn+1]));
|
2020-07-31 11:31:32 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
cd |= (1<<k[p]);
|
|
|
|
cd &= ~(1<<j[p]);
|
|
|
|
|
|
|
|
if (c < MAX_TRACE) { // NP
|
|
|
|
tr[c].k=2*ci;
|
|
|
|
tr[c].d=1./((double) q2 - (double) q*(double) q /(double) (numEntries));
|
|
|
|
code[c]=cd;
|
|
|
|
c++;
|
|
|
|
} else {
|
|
|
|
// What to do here?
|
|
|
|
tr[c].k=0;
|
|
|
|
tr[c].d=0;
|
|
|
|
code[c]=0;
|
|
|
|
*trcnt=0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
k[p]=j[p];
|
|
|
|
}
|
|
|
|
}
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
} while (rescan);
|
2020-07-31 11:31:32 +08:00
|
|
|
c0++;
|
2021-09-08 10:54:22 +08:00
|
|
|
if (numClusters < 8) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 7) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 6) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 5) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 4) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 3) break;
|
|
|
|
}
|
|
|
|
if (numClusters < 2) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*trcnt=c;
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
double optQuantAnD(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][DIMENSION],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index[MAX_ENTRIES],
|
|
|
|
double out[MAX_ENTRIES][DIMENSION],
|
|
|
|
double direction [DIMENSION],double *step
|
2021-09-08 10:54:22 +08:00
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int index_[MAX_ENTRIES];
|
|
|
|
int maxTry=MAX_TRY*10;
|
|
|
|
int try_two=50;
|
|
|
|
int i,j,k;
|
|
|
|
double t,s;
|
|
|
|
double centered[MAX_ENTRIES][DIMENSION];
|
|
|
|
double mean[DIMENSION];
|
|
|
|
double cov[DIMENSION][DIMENSION];
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int order_[MAX_ENTRIES];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace(centered, numEntries, mean);
|
|
|
|
covariance(centered, numEntries, cov);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t==0 || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector(cov, direction);
|
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
int quant_AnD_Shell_Calls = 0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
|
|
|
int done =0;
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (i) {
|
|
|
|
do {
|
|
|
|
double q;
|
|
|
|
q=s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=centered[k][j]*index[k];
|
|
|
|
q+= direction[j]* direction[j];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
assert(t !=0);
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
// We need to requantize
|
|
|
|
|
|
|
|
q = sqrt(q);
|
2020-07-31 11:31:32 +08:00
|
|
|
t *=q;
|
|
|
|
|
|
|
|
if (q !=0)
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
|
|
|
|
|
|
|
// direction normalized
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project(centered, numEntries, direction, projected);
|
2020-07-31 11:31:32 +08:00
|
|
|
sortProjection(projected, order_, numEntries);
|
|
|
|
|
|
|
|
int index__[MAX_ENTRIES];
|
|
|
|
|
|
|
|
// it's projected and centered; cluster centers are (index[i]-s)*t (*dir)
|
|
|
|
k=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
|
|
|
while (projected[order_[j]] > (k+0.5 -s)*t && k < numClusters-1)
|
2020-07-31 11:31:32 +08:00
|
|
|
k++;
|
|
|
|
index__[order_[j]]=k;
|
|
|
|
}
|
|
|
|
done =1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
done = (done && (index__[j]==index[j]));
|
|
|
|
index[j]=index__[j];
|
|
|
|
}
|
|
|
|
} while (! done && try_two--);
|
2021-09-08 10:54:22 +08:00
|
|
|
if (i==1)
|
|
|
|
for (j=0; j < numEntries; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
index_[j]=index[j];
|
|
|
|
else {
|
|
|
|
done =1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
done = (done && (index_[j]==index[j]));
|
|
|
|
index_[j]=index_[j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
if (done)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
quant_AnD_Shell_Calls++;
|
2021-09-08 10:54:22 +08:00
|
|
|
quant_AnD_Shell(projected, numClusters,numEntries, index);
|
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(("->quant_AnD_Shell [%2d]",quant_AnD_Shell_Calls));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double q=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=centered[k][j]*index[k];
|
2021-09-08 10:54:22 +08:00
|
|
|
q+= direction[j]* direction[j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
2021-09-08 10:54:22 +08:00
|
|
|
if (t==0)
|
2020-07-31 11:31:32 +08:00
|
|
|
DbgTrace(("l;lkjk"));
|
|
|
|
#endif
|
|
|
|
assert(t !=0);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<DIMENSION; j++)
|
|
|
|
out[i][j]=mean[j]+direction[j]*t*(index[i]-s);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
// normalize direction for output
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
q=sqrt(q);
|
|
|
|
*step=t*q;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<DIMENSION; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
return totalError(data,out,numEntries);
|
|
|
|
}
|
|
|
|
|
|
|
|
double optQuantAnD_d(
|
2021-09-08 10:54:22 +08:00
|
|
|
double data[MAX_ENTRIES][MAX_DIMENSION_BIG],
|
2020-07-31 11:31:32 +08:00
|
|
|
int numEntries, int numClusters, int index[MAX_ENTRIES],
|
|
|
|
double out[MAX_ENTRIES][MAX_DIMENSION_BIG],
|
|
|
|
double direction [MAX_DIMENSION_BIG],double *step,
|
|
|
|
int dimension
|
2021-09-08 10:54:22 +08:00
|
|
|
) {
|
2020-07-31 11:31:32 +08:00
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(());
|
|
|
|
#endif
|
|
|
|
int index_[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int maxTry=MAX_TRY*10;
|
|
|
|
int try_two=50;
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
double t,s;
|
|
|
|
|
|
|
|
double centered[MAX_ENTRIES][MAX_DIMENSION_BIG];
|
|
|
|
|
|
|
|
double mean[MAX_DIMENSION_BIG];
|
|
|
|
|
|
|
|
double cov[MAX_DIMENSION_BIG][MAX_DIMENSION_BIG];
|
|
|
|
|
|
|
|
double projected[MAX_ENTRIES];
|
|
|
|
|
|
|
|
int order_[MAX_ENTRIES];
|
|
|
|
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
centered[i][j]=data[i][j];
|
|
|
|
|
|
|
|
centerInPlace_d(centered, numEntries, mean, dimension);
|
|
|
|
covariance_d(centered, numEntries, cov, dimension);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
// check if they all are the same
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
|
|
|
t+= cov[j][j];
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
if (t<(1./256.) || numEntries==0) {
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<numEntries; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
index[i]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
out[i][j]=mean[j];
|
|
|
|
}
|
|
|
|
return 0.;
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
eigenVector_d(cov, direction, dimension);
|
|
|
|
project_d(centered, numEntries, direction, projected, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
int quant_AnD_Shell_Calls = 0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (i=0; i<maxTry; i++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
int done =0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (i) {
|
|
|
|
do {
|
2020-07-31 11:31:32 +08:00
|
|
|
double q;
|
|
|
|
q=s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=centered[k][j]*index[k];
|
|
|
|
q+= direction[j]* direction[j];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
assert(t !=0);
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
// We need to requantize
|
|
|
|
|
|
|
|
q = sqrt(q);
|
2020-07-31 11:31:32 +08:00
|
|
|
t *=q;
|
|
|
|
|
|
|
|
if (q !=0)
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
|
|
|
|
|
|
|
// direction normalized
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
project_d(centered, numEntries, direction, projected, dimension);
|
2020-07-31 11:31:32 +08:00
|
|
|
sortProjection(projected, order_, numEntries);
|
|
|
|
|
|
|
|
int index__[MAX_ENTRIES];
|
|
|
|
|
|
|
|
// it's projected and centered; cluster centers are (index[i]-s)*t (*dir)
|
|
|
|
k=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
|
|
|
while (projected[order_[j]] > (k+0.5 -s)*t && k < numClusters-1)
|
2020-07-31 11:31:32 +08:00
|
|
|
k++;
|
|
|
|
index__[order_[j]]=k;
|
|
|
|
}
|
|
|
|
done =1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
done = (done && (index__[j]==index[j]));
|
|
|
|
index[j]=index__[j];
|
|
|
|
}
|
|
|
|
} while (! done && try_two--);
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
if (i==1)
|
|
|
|
for (j=0; j < numEntries; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
index_[j]=index[j];
|
2021-09-08 10:54:22 +08:00
|
|
|
else {
|
2020-07-31 11:31:32 +08:00
|
|
|
done =1;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j < numEntries; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
done = (done && (index_[j]==index[j]));
|
|
|
|
index_[j]=index_[j];
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
if (done)
|
2020-07-31 11:31:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
quant_AnD_Shell_Calls++;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
quant_AnD_Shell(projected, numClusters,numEntries, index);
|
2020-07-31 11:31:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_DBGTRACE
|
|
|
|
DbgTrace(("->quant_AnD_Shell [%2d]",quant_AnD_Shell_Calls));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
s=t=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
double q=0;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
s+= index[k];
|
|
|
|
t+= index[k]*index[k];
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++) {
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]=0;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (k=0; k<numEntries; k++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]+=centered[k][j]*index[k];
|
|
|
|
q+= direction[j]* direction[j];
|
|
|
|
}
|
|
|
|
|
|
|
|
s /= (double) numEntries;
|
|
|
|
|
|
|
|
t = t - s * s * (double) numEntries;
|
|
|
|
|
2021-09-08 10:54:22 +08:00
|
|
|
assert(t !=0);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
t = (t == 0 ? 0. : 1/t);
|
2021-09-08 10:54:22 +08:00
|
|
|
|
|
|
|
for (i=0; i<numEntries; i++)
|
|
|
|
for (j=0; j<dimension; j++)
|
|
|
|
out[i][j]=mean[j]+direction[j]*t*(index[i]-s);
|
2020-07-31 11:31:32 +08:00
|
|
|
|
|
|
|
// normalize direction for output
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
q=sqrt(q);
|
|
|
|
*step=t*q;
|
2021-09-08 10:54:22 +08:00
|
|
|
for (j=0; j<dimension; j++)
|
2020-07-31 11:31:32 +08:00
|
|
|
direction[j]/=q;
|
2021-09-08 10:54:22 +08:00
|
|
|
|
2020-07-31 11:31:32 +08:00
|
|
|
return totalError_d(data,out,numEntries, dimension);
|
|
|
|
}
|
|
|
|
|