⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transhash.c

📁 Hausdorff Distance for Image Recognition
💻 C
字号:
/* * * $Header: /usr/u/wjr/vision/r-h/RCS/transhash.c,v 1.5 1993/11/04 21:11:14 wjr Exp $ * * Copyright (c) 1992, 1993 Cornell University.  All Rights Reserved.   *   * Use, reproduction, preparation of derivative works, and distribution * of this software is permitted.  Any copy of this software or of any * derivative work must include both the above copyright notice of * Cornell University and this paragraph.  Any distribution of this * software or derivative works must comply with all applicable United * States export control laws.  This software is made available AS IS, * and CORNELL UNIVERSITY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE, AND NOTWITHSTANDING ANY OTHER * PROVISION CONTAINED HEREIN, ANY LIABILITY FOR DAMAGES RESULTING FROM * THE SOFTWARE OR ITS USE IS EXPRESSLY DISCLAIMED, WHETHER ARISING IN * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, EVEN IF * CORNELL UNIVERSITY IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */static char rcsid[] = "@(#)$Header: /usr/u/wjr/vision/r-h/RCS/transhash.c,v 1.5 1993/11/04 21:11:14 wjr Exp $";#include "list.h"#include "misc.h"#include "transhash.h"/* * What's a TransHash, anyway? Well, it's a place to record some * basic information about a bunch of transformations, each of which consists * of two integers, referred to as x, y, each of which is * known to have bounded range, and whose values are spaced apart by known * steps (i.e. x can take on values, lowX, lowX + stepX, ..., highX-1, and * similarly for y). We want to know, for each value, whether or not * it is in the hash table. We also want cheap addition and deletion. * Actually, highX-lowX need not be conguent to zero mod stepX, and as long * as you don't try to feed it two entries which are within stepX of each * other, it will do fine. * * The TransHash structure contains a number of Lists, used as buckets. * Each List contains all the entries added so far which hash to that * bucket. The hashing function is simple: just add up the four values * (correcting for the step size and the ranges). It remains to be seen how * well this works... * * What do the routines do? Well, thNew() does what you'd expect: gives * you a new, empty, hash table. If it can't, it gives you (TransHash *)NULL. * thFree() gets rid of your old, unfashionable, hash table. * thAdd() makes a mark that this point is in the table, and returns TRUE; * it returns FALSE if it can't. Adding the same point more than once is * an error. * thRem() removes a point. If it isn't in the table, you get an assertion * failure. * thIsIn tells you if a point is in the table. * thGetLowest gives you the lowest-sum point in the table (point with * smallest x+y, with a possible error of stepX+stepY). If the table * is empty, it gives you FALSE, otherwise TRUE. * * You can tell it to store a void * pointer along with an entry when you * initially thAdd() it; use thGet() to get it back. * *//* * Internally, the hash function just adds the two components, and also * separates out some of the lower-order bits; entries which add up to * the same value are grouped based on the low bits of the two values. *//* How many low bits to pull out as additional hash bits */#define	LOWBITS	2/* The mask to get these */#define	LOWMASK	((1 << LOWBITS) - 1)/* With 2 components, pulling out LOWBITS gets us this many groups */#define	NHASHGROUPS	(1 << (2 * LOWBITS))static int hash(TransHash *th, int x, int y);/* This is the structure we hang off the ListNodes */typedef struct {    int x, y;    void *userdata;    } TransHashEntry;TransHash *thNew(int lowX, int highX, int stepX,      int lowY, int highY, int stepY){    TransHash *newth;    int nlist;    int i;    assert(lowX < highX);    assert(lowY < highY);    newth = (TransHash *)malloc(sizeof(*newth));    if (newth == (TransHash *)NULL) {	return((TransHash *)NULL);	}    /*     * How many entries can there be in the hash table?     * Well, feed in the highest values possible (highX - 1, highY - 1 etc),     * shift by the space we're saving for the low-order bits (NHASHGROUPS),     * and add then the highest values for the low-order bits possible (i.e. up     * to an additional NHASHGROUPS - 1); this gives us the highest     * possible hash value. Since they start at zero, add one.     */    nlist = ((highX - 1 - lowX) / stepX + (highY - 1 - lowY) / stepY) *	NHASHGROUPS + NHASHGROUPS;    newth->listarr = (List *)malloc((unsigned)nlist * sizeof(List));    if (newth->listarr == (List *)NULL) {	free((void *)newth);	return((TransHash *)NULL);	}    newth->lowX = lowX;    newth->highX = highX;    newth->stepX = stepX;    newth->lowY = lowY;    newth->highY = highY;    newth->stepY = stepY;    newth->nlist = nlist;    for (i = 0; i < nlist; i++) {	newth->listarr[i] = NULLLIST;	}    newth->lowbucket = nlist;    return(newth);    }void thFree(TransHash *th){    int i;    List l;    ListNode ln;    TransHashEntry *the;#ifdef INSTRUMENT    int ntot = 0;    int nmax = 0;    int nli = 0;#endif    assert(th != (TransHash *)NULL);    assert(th->listarr != (List *)NULL);    /* Free all the Lists and the stuff hung on them */    for (i = 0; i < th->nlist; i++) {	if (th->listarr[i] != NULLLIST) {	    l = th->listarr[i];#ifdef INSTRUMENT	    nli++;	    nmax = MAX(nmax, liLen(l));	    ntot += liLen(l);#endif	    foreach (ln, l) {		the = (TransHashEntry *)liGet(ln);		assert(the != (TransHashEntry *)NULL);		free((void *)the);		}	    liFree(l);	    }	}#ifdef INSTRUMENT    DEBUG( "freed with %d/%d lists, max %d, mean %f\n",	  nli, th->nlist, nmax, ntot / (double)nli);#endif    free((void *)th->listarr);    free((void *)th);    }boolean thAdd(TransHash *th, int x, int y, void *userdata){    int bucket;    List l;    ListNode ln;    TransHashEntry *the;        assert(th != (TransHash *)NULL);    assert(!thIsIn(th, x, y));    the = (TransHashEntry *)malloc(sizeof(TransHashEntry));    if (the == (TransHashEntry *)NULL) {	return(FALSE);	}    the->x = x;    the->y = y;    the->userdata = userdata;    bucket = hash(th, x, y);    l = th->listarr[bucket];    if (l == NULLLIST) {	/* First hit on this bucket */	l = liNew();	if (l == NULLLIST) {	    free((void *)the);	    return(FALSE);	    }	th->listarr[bucket] = l;	}    /* Add to the collision chain */    ln = liAdd(l, (void *)the);    if (ln == NULLLISTNODE) {	/* Don't free l - th now owns it */	free((void *)the);	return(FALSE);	}    /* Make sure we keep track of the lowest bucket */    th->lowbucket = MIN(th->lowbucket, bucket);    return(TRUE);    }void thRem(TransHash *th, int x, int y){    int bucket;    List l;    ListNode ln;    TransHashEntry *the;        assert(th != (TransHash *)NULL);    assert(thIsIn(th, x, y));    bucket = hash(th, x, y);    l = th->listarr[bucket];    assert(l != NULLLIST);    foreach (ln, l) {	the = (TransHashEntry *)liGet(ln);	assert(the != (TransHashEntry *)NULL);	if ((the->x == x) && (the->y == y)) {	    /* Found it. */	    liRem(ln);	    free((void *)the);	    break;	    }	}    }booleanthIsIn(TransHash *th, int x, int y){    int bucket;    List l;    ListNode ln;    TransHashEntry *the;        assert(th != (TransHash *)NULL);    bucket = hash(th, x, y);    l = th->listarr[bucket];    if (l == NULLLIST) {	/* No bucket chain - can't be there. */	return(FALSE);	}    foreach (ln, l) {	the = (TransHashEntry *)liGet(ln);	assert(the != (TransHashEntry *)NULL);	if ((the->x == x) && (the->y == y)) {	    /* Found it. */	    return(TRUE);	    }	}    return(FALSE);    }booleanthGetLowest(TransHash *th, int *x, int *y){    int i;    List l;    ListNode ln;    TransHashEntry *the;    assert(th != (TransHash *)NULL);    assert(x != (int *)NULL);    assert(y != (int *)NULL);    for (i = th->lowbucket; i < th->nlist; i++) {	if (th->listarr[i] != NULLLIST) {	    l = th->listarr[i];	    ln = liFirst(l);	    if (ln != NULLLISTNODE) {		/* Found one */		the = (TransHashEntry *)liGet(ln);		assert(the != (TransHashEntry *)NULL);		*x = the->x;		*y = the->y;		/* This is the lowest non-empty bucket */		th->lowbucket = i;		return(TRUE);		}	    }			}    return(FALSE);    }void *thGet(TransHash *th, int x, int y){    int bucket;    List l;    ListNode ln;    TransHashEntry *the;        assert(th != (TransHash *)NULL);    assert(thIsIn(th, x, y));    bucket = hash(th, x, y);    l = th->listarr[bucket];    assert(l != NULLLIST);    foreach (ln, l) {	the = (TransHashEntry *)liGet(ln);	assert(the != (TransHashEntry *)NULL);	if ((the->x == x) && (the->y == y)) {	    /* Found it. */	    return(the->userdata);	    }	}    panic("thIsIn says it's there...");    }/* * Given a point, find out which bucket it hashes to. */static inthash(TransHash *th, int x, int y){    int bucket;    int hashx, hashy;    assert(th != (TransHash *)NULL);    assert(th->lowX <= x);    assert(x < th->highX);    assert(th->lowY <= y);    assert(y < th->highY);    hashx = (x - th->lowX) / th->stepX;    hashy = (y - th->lowY) / th->stepY;    bucket = (((hashx + hashy) << (2 * LOWBITS)) |	      ((hashx & LOWMASK) << (LOWBITS)) |	      ((hashy & LOWMASK)));	        assert(bucket < th->nlist);    return(bucket);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -