home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Los Alamos National Laboratory
/
LANL_CD.ISO
/
software
/
compres
/
src
/
search.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-11
|
5KB
|
203 lines
/****************************************************************
COPYRIGHT (C) 1992 UNIVERSITY OF CALIFORNIA
***************************************************************/
#include <math.h>
#include "kdnode.h"
#define NULL 0
int ClosestIndex;
float *LoBound, *HiBound, ClosestDist, ClosestDistSq;
/****************************************************************/
int FindClosestVector(OKDTree, k, ncv, cbook, Z, CVDist)
int k, ncv;
float *cbook, *Z, *CVDist;
struct KDTreeNode *OKDTree;
{
int i;
ClosestDist = ClosestDistSq = 1.e30;
LoBound = (float*)malloc(k*sizeof(float));
HiBound = (float*)malloc(k*sizeof(float));
if(!LoBound || !HiBound ) {
printf("ERROR: Not enough room for malloc\n");
exit(-1);
}
for(i = 0; i < k; i++) {
LoBound[i] = -1.e30;
HiBound[i] = 1.e30;
}
SearchOKDTree(OKDTree, k, ncv, cbook, Z);
*CVDist = ClosestDist;
return ClosestIndex;
}
/****************************************************************/
int SearchOKDTree(Node, k, ncv, cbook, Z)
struct KDTreeNode *Node;
int k, ncv;
float *cbook, *Z;
{
int Index, i, Axis;
float Part, Store;
register float xx, delta, *cbptr, *max, *zptr;
/*________________________________________________________________*/
if(Node->Left == NULL) { /* Terminal node */
for(i = 0; i < Node->ListSize; i++) {
zptr = Z;
cbptr = cbook + (Index = Node->List[i])*k;
max = cbptr + k;
xx = 0.;
while(cbptr < max) {
delta = *zptr++ - *cbptr++;
xx += delta*delta;
if(xx > ClosestDistSq)
break;
}
if(xx < ClosestDistSq) {
ClosestIndex = Index;
ClosestDistSq = xx;
}
}
ClosestDist = sqrt(ClosestDistSq);
if(BallWithinBounds(Z, k))
return -1;
return 0;
}
/*________________________________________________________________*/
else { /* Nonterminal node */
if(Z[Axis = Node->KeyIndex] <= (Part = Node->PartitionValue)) {
Store = HiBound[Axis];
HiBound[Axis] = Part;
i = SearchOKDTree(Node->Left, k, ncv, cbook, Z);
HiBound[Axis] = Store;
if(i == -1)
return -1;
}
else { /* Search the right node */
Store = LoBound[Axis];
LoBound[Axis] = Part;
i = SearchOKDTree(Node->Right, k, ncv, cbook, Z);
LoBound[Axis] = Store;
if(i == -1)
return -1;
}
if(Z[Axis] <= Part) { /* Search the right node */
Store = LoBound[Axis];
LoBound[Axis] = Part;
if(BoundsOverlapBall(Z, k)) {
i = SearchOKDTree(Node->Right, k, ncv, cbook, Z);
LoBound[Axis] = Store;
if(i == -1)
return -1;
}
else LoBound[Axis] = Store;
}
else { /* Search the left node */
Store = HiBound[Axis];
HiBound[Axis] = Part;
if(BoundsOverlapBall(Z, k)) {
i = SearchOKDTree(Node->Left, k, ncv, cbook, Z);
HiBound[Axis] = Store;
if(i == -1)
return -1;
}
else HiBound[Axis] = Store;
}
if(BallWithinBounds(Z, k))
return -1;
return 0;
}
}
/****************************************************************/
int BallWithinBounds(z, k)
register float *z;
int k;
{
register float delta, *lptr, *hptr, *max;
lptr = LoBound;
hptr = HiBound;
max = z + k;
while(z < max) {
delta = *z - *lptr++;
if(delta <= 0.)
delta = -delta;
if(delta <= ClosestDist)
return 0;
delta = *z++ - *hptr++;
if(delta <= 0.)
delta = -delta;
if(delta <= ClosestDist)
return 0;
}
return 1;
}
/****************************************************************/
int BoundsOverlapBall(z, k)
register float *z;
int k;
{
register float sum = 0., delta, *lptr, *hptr, *max;
lptr = LoBound;
hptr = HiBound;
max = z + k;
while(z < max) {
if(*z < *lptr)
delta = *z - *lptr;
else if(*z > *hptr)
delta = *z - *hptr;
else
delta = 0;
sum += delta*delta;
if(sum > ClosestDistSq)
return 0;
z++;
lptr++;
hptr++;
}
return 1;
}