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

📄 rfst.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 4 页
字号:
			i1 = index [j];			i2 = index [i];			p1 = &(pts -> a [i1]);			p2 = &(pts -> a [i2]);			if ((p1 -> y > p2 -> y) OR			    ((p1 -> y EQ p2 -> y) AND			     ((p1 -> x > p2 -> x) OR			      ((p1 -> x EQ p2 -> x) AND			       (i1 > i2))))) {				/* Greatest child is smaller.  Sift-	*/				/* down is done. */				break;			}			/* Sift down and continue. */			index [j] = i2;			index [i] = i1;			j = i;		}	}	/* Now do actual sorting.  Exchange first/last and sift down. */	while (n > 1) {		/* Largest is at index [0], swap with index [n-1],	*/		/* thereby putting it into final position.		*/		--n;		i = index [0];		index [0] = index [n];		index [n] = i;		/* Now restore the heap by sifting index [0] down. */		j = 0;		for (;;) {			i = (j << 1) + 1;			if (i + 1 < n) {				/* Increment i (to right subchild of j) */				/* if the right subchild is greater. */				i1 = index [i];				i2 = index [i + 1];				p1 = &(pts -> a [i1]);				p2 = &(pts -> a [i2]);				if ((p2 -> y > p1 -> y) OR				    ((p2 -> y EQ p1 -> y) AND				     ((p2 -> x > p1 -> x) OR				      ((p2 -> x EQ p1 -> x) AND				       (i2 > i1))))) {					++i;				}			}			if (i >= n) {				/* Hit bottom of heap, sift-down is done. */				break;			}			i1 = index [j];			i2 = index [i];			p1 = &(pts -> a [i1]);			p2 = &(pts -> a [i2]);			if ((p1 -> y > p2 -> y) OR			    ((p1 -> y EQ p2 -> y) AND			     ((p1 -> x > p2 -> x) OR			      ((p1 -> x EQ p2 -> x) AND			       (i1 > i2))))) {				/* Greatest child is smaller.  Sift-	*/				/* down is done. */				break;			}			/* Sift down and continue. */			index [j] = i2;			index [i] = i1;			j = i;		}	}	return (index);}/* * This routine finds all pairs of points whose coordinates are exactly * identical.  This is a degeneracy that can cause successive algorithms * much heartburn, so we take care of them immediately by keeping only * the earliest (lowest pnum) point, and marking the others as duplicates. * We generate a partition of such terminals into subsets -- if terminals * A and B reside in the same subset then they have identical coordinates. * We refer to such a subset as a Duplicate Terminal Group. * * For each terminal group we retain ONLY THE FIRST member -- the terminal * map bits are turned OFF for all other members of a terminal group, * effectively eliminating those terminals from the problem. */	static	intgenerate_duplicate_terminal_groups (struct pset *		pts,	/* IN - original terminal set */int *			xorder, /* IN - terminal numbers sorted by X coord */int ***			grps	/* OUT - duplicate terminal groups */){int			i;int			j;int			n;int			n_grps;struct point *		p0;struct point *		p1;struct point *		p2;int *			ip;int **			real_ptrs;int *			real_terms;int **			ptrs;int *			terms;	n = pts -> n;	n_grps = 0;	ptrs	= NEWA (n + 1, int *);	terms	= NEWA (n, int);	ip = &terms [0];	for (i = 1; i < n; ) {		p0 = &(pts -> a [xorder [i - 1]]);		p1 = &(pts -> a [xorder [i]]);		if ((p0 -> y NE p1 -> y) OR (p0 -> x NE p1 -> x)) {			/* Not identical. */			++i;			continue;		}		/* Terminals xorder[i-1] and xorder[i] are identical. */		for (j = i + 1; j < n; j++) {			p2 = &(pts -> a [xorder [j]]);			if (p0 -> y NE p2 -> y) break;			if (p0 -> x NE p2 -> x) break;		}		/* j now points to the first non-equal terminal */		/* Make a new duplicate terminal group... */		ptrs [n_grps++] = ip;		*ip++ = xorder [i - 1];		while (i < j) {			*ip++ = xorder [i++];		}		/* Skip whole group of coincident points and continue */	}	ptrs [n_grps] = ip;	if (n_grps <= 0) {		*grps = NULL;	}	else {		/* Transfer to permanent memory of proper size... */		real_ptrs = NEWA (n_grps + 1, int *);		real_terms = NEWA (ip - terms, int);		(void) memcpy ((char *) real_terms,			       (char *) terms,			       (ip - terms) * sizeof (int));		for (i = 0; i <= n_grps; i++) {			real_ptrs [i] = &real_terms [ptrs [i] - ptrs [0]];		}		*grps = real_ptrs;	}	free ((char *) terms);	free ((char *) ptrs);	return (n_grps);}/* * This routine removes all but the first terminal in each duplicate * terminal group.  We also prepare arrays for mapping forward from * old to new terminal numbers, and backward from new terminal numbers * to old. */	static	struct pset *remove_duplicates (struct pset *		pts,		/* IN - original point set */int			ndg,		/* IN - number of duplicate groups */int **			list,		/* IN - list of duplicate groups */int **			fwd_map_ptr,	/* OUT - map to renumber old to new */int **			rev_map_ptr	/* OUT - map to renumber new to old */){int		i;int		j;int		n;int		kmasks;int		numdel;int		new_n;int *		ip1;int *		ip2;int *		fwd;int *		rev;bitmap_t *	deleted;struct pset *	newpts;	n = pts -> n;	kmasks = BMAP_ELTS (n);	deleted = NEWA (kmasks, bitmap_t);	for (i = 0; i < kmasks; i++) {		deleted [i] = 0;	}	numdel = 0;	for (i = 0; i < ndg; i++) {		ip1 = list [i];		ip2 = list [i + 1];		/* Retain the first in this group, exclude all	*/		/* of the others...				*/		while (++ip1 < ip2) {			if (BITON (deleted, *ip1)) {				fatal ("remove_duplicates: Bug 1.");			}			++numdel;			SETBIT (deleted, *ip1);		}	}	new_n = n - numdel;	fwd = NEWA (n, int);	rev = NEWA (new_n, int);	newpts = NEW_PSET (new_n);	memset (newpts, 0, PSET_SIZE (new_n));	newpts -> n = new_n;	j = 0;	for (i = 0; i < n; i++) {		if (BITON (deleted, i)) {			fwd [i] = -1;		}		else {			newpts -> a [j].x		= pts -> a [i].x;			newpts -> a [j].y		= pts -> a [i].y;			newpts -> a [j].pnum		= j;			rev [j] = i;			fwd [i] = j;			++j;		}	}	free ((char *) deleted);	*fwd_map_ptr = fwd;	*rev_map_ptr = rev;	return (newpts);}/* * Compute the RFSTs for the given set of terminals, which are now * guaranteed to be unique. */	static	voidcompute_rfsts_for_unique_terminals (struct rinfo *		rip	/* IN - global RFST info */){int			i;int			n;int			dir;int			nedges;struct pset *		pts;struct edge *		ep;struct edge *		mst_edges;struct rlist *		rp;dist_t			mst_len;double			ub_shortleg [2];char			buf1 [32];	pts = rip -> pts;	n = pts -> n;	compute_successors (rip);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute Successors:     %s\n", buf1);	}	rip -> empty_rect = init_empty_rectangles (pts, rip -> succ [0]);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Empty Rectangles:       %s\n", buf1);	}	compute_ub0 (rip);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute UB0:            %s\n", buf1);	}	mst_edges = NEWA (n - 1, struct edge);	nedges = rect_mst (pts, mst_edges, rip -> empty_rect);	if (nedges NE n - 1) {		fatal ("compute_rfsts_for_unique_terminals: Bug 1.");	}	mst_len = 0.0;	ep = mst_edges;	for (i = 0; i < nedges; ep++, i++) {		mst_len += ep -> len;	}	rip -> mst_length = mst_len;	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute MST:            %s\n", buf1);	}	rip -> bsd = compute_bsd (nedges, mst_edges, 0);	free ((char *) mst_edges);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute BSD:            %s\n", buf1);	}	compute_zt (rip);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute ZT:             %s\n", buf1);	}	compute_ub1 (rip);	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Compute UB1:            %s\n", buf1);	}	/*	 * Preprocessing finished.  Start growing FSTs!	 */	rip -> terms		= NEWA (n, int);	rip -> longterms	= NEWA (n + 1, int);	rip -> maxedges		= NEWA (n, dist_t);	rip -> shortterm	= NEWA (n, int);	rip -> lrindex		= NEWA (n, int);	rip -> term_check	= NEWA (n, bool);	rip -> hash		= NEWA (n, struct rlist *);	for (i = 0; i < n; i++) {		rip -> lrindex [i] = 0;		rip -> term_check [i] = FALSE;		rip -> hash [i] = NULL;	}	rip -> list.forw	= &(rip -> list);	rip -> list.back	= &(rip -> list);	rip -> fsts_checked = 0;	ub_shortleg [0] = INF_DISTANCE;	ub_shortleg [1] = INF_DISTANCE;	if (MaxFSTSize EQ 0) MaxFSTSize = n;	for (dir = 0; dir < 2; dir++) {		for (i = 0; i < n; i++) {			rip -> terms [0]	= i;			rip -> maxedges [i]	= 0.0;			/* Long leg candidate list is initially empty,	*/			/* add candidates on demand.			*/			rip -> longterms [0]	= i;			rip -> longterms [1]	= -1;			grow_RFST (rip,				   1,		/* size */				   0.0,		/* length */				   dir,				   0.0,		/* ub_length */				   ub_shortleg,				   0);		/* longindex */#if DO_STATISTICS			for (j = 0; longterms [j] >= 0; j++) {				++long_leg_count;			}#endif		}	}	/* Finally add MST-edges */	ep = &(rip -> bsd -> mst_edges [1]);	for (i = 1; i < n; i++) {		rip -> terms [0] = ep -> p1;		rip -> terms [1] = ep -> p2;		test_and_save_fst (rip,				   2,				   ep -> len,				   0,				   TYPE_1);		++ep;	}#if DO_STATISTICS	fprintf (stderr, "Total FSTs checked: %d\n", rip -> fsts_checked);#endif	if (Print_Detailed_Timings) {		convert_delta_cpu_time (buf1);		fprintf (stderr, "Grow FSTs:              %s\n", buf1);	}	/* Disconnect FSTs from hash table. */	for (rp = rip -> list.forw;	     rp NE &(rip -> list);	     rp = rp -> forw) {		rp -> next = NULL;	}	/* Clean up. */	free ((char *) (rip -> hash));		rip -> hash = NULL;	free ((char *) (rip -> term_check));	rip -> term_check = NULL;	free ((char *) (rip -> lrindex));	rip -> lrindex = NULL;	free ((char *) (rip -> shortterm));	rip -> shortterm = NULL;	free ((char *) (rip -> maxedges));	rip -> maxedges = NULL;	free ((char *) (rip -> longterms));	rip -> longterms = NULL;	free ((char *) (rip -> terms));		rip -> terms = NULL;	free ((char *) (rip -> ub1 [0]));	free ((char *) (rip -> zt [0] [0]));	free ((char *) (rip -> zt [0]));	shutdown_bsd (rip -> bsd);	free ((char *) (rip -> ub0 [0]));	free ((char *) (rip -> empty_rect));	rip -> empty_rect = NULL;	free ((char *) (rip -> succ [0]));	memset (&(rip -> succ), 0, sizeof (rip -> succ));	memset (&(rip -> ub0),	0, sizeof (rip -> ub0));	memset (&(rip -> ub1),	0, sizeof (rip -> ub1));	memset (&(rip -> zt),	0, sizeof (rip -> zt));}/* * Sort the terminals by both X and Y coordinates, and then create the * successor lists.  These permit us to start from a random terminal and * traverse all remaining terminals in order by one of the four compass * directions. */	static	voidcompute_successors (struct rinfo *		rip		/* The global RFST info */){int			i;int			n;struct pset *		pts;int *			index;int *			succ;	pts = rip -> pts;	n = pts -> n;	/* Allocate permanent successor lists. */	succ = NEWA (4 * n, int);	rip -> succ [0] = succ;		succ += n;	rip -> succ [1] = succ;		succ += n;	rip -> succ [2] = succ;		succ += n;	rip -> succ [3] = succ;	rip -> succ [4] = rip -> succ [0];	rip -> succ [5] = rip -> succ [1];	rip -> succ [6] = rip -> succ [2];	/* Get terminal numbers sorted by X coordinate. */	index = rip -> x_order;	/* Set direction 0 (due east) successors. */	succ = rip -> succ [0];	for (i = 1; i < n; i++) {		succ [index [i - 1]] = index [i];	}	succ [index [i - 1]] = -1;	/* Set direction 2 (due west) successors. */	succ = rip -> succ [2];	for (i = 1; i < n; i++) {		succ [index [i]] = index [i - 1];	}	succ [index [0]] = -1;	/* Get terminal numbers sorted by Y coordinate. */	index = rip -> y_order;	/* Set direction 1 (due north) successors. */	succ = rip -> succ [1];	for (i = 1; i < n; i++) {		succ [index [i - 1]] = index [i];	}	succ [index [i - 1]] = -1;	/* Set direction 3 (due south) successors. */	succ = rip -> succ [3];	for (i = 1; i < n; i++) {		succ [index [i]] = index [i - 1];	}	succ [index [0]] = -1;}/* * Compute the UB0 bounds. */	static	voidcompute_ub0 (struct rinfo *		rip		/* IN/OUT - global RFST info */){int			i;int			j;int			n;int			dir;struct pset *		pts;struct point *		p1;struct point *		p2;int *			succ;dist_t *		array;dstdiroff_t		dir_off;dstdiroff_t		dirp_off;double			bound;double			d1, d2, d3;	pts = rip -> pts;	n = pts -> n;	array = NEWA (4 * n, dist_t);	rip -> ub0 [0]	= array;	array += n;	rip -> ub0 [1]	= array;	array += n;	rip -> ub0 [2]	= array;	array += n;	rip -> ub0 [3]	= array;	rip -> ub0 [4]	= rip -> ub0 [0];	rip -> ub0 [5]	= rip -> ub0 [1];	rip -> ub0 [6]	= rip -> ub0 [2];	for (dir = 0; dir < 4; dir++) {		array =	 rip -> ub0 [dir];		succ = rip -> succ [dir];		dir_off = DSTDIR_GETOFFSET (dir);		dirp_off = DSTDIR_GETOFFSET (dir + 1);		p1 = &(pts -> a [0]);		for (i = 0; i < n; i++, p1++) {			bound = INF_DISTANCE;			for (j = succ [i]; j >= 0; j = succ [j]) {				p2 = &(pts -> a [j]);				d1 = DSTDIR_OFFSET (p1, p2, dir_off);				if (d1 > bound) break;				d2 = DSTDIR_OFFSET (p1, p2, dirp_off);				if (d1 > d2) {					d3 = d1 + d2;	/* RDIST (p1,p2) */					if (d3 < bound) {						bound = d3;					}				}			}			array [i] = bound;		}	}}/* * Find the short leg candidates for each terminal i and direction. */	static	voidcompute_zt (struct rinfo *		rip		/* IN/OUT - global RFST info */){int			i;int			j;int			n;int			dir;int			dirp;int			lr;int			index;struct pset *		pts;struct point *		p1;struct point *		p2;int *			succ;int *			ip;int *			ip1;int **			zt;dstdiroff_t		dir_off;dstdiroff_t		dir1_off;lrdiroff_t		lrdir_off;dist_t *		ub0;dist_t *		ub0p;dist_t			d1, d2;dist_t			limit;dist_t			b;struct ibuf *		root;struct ibuf *		ibp;struct ibuf **		hookp;int *			bufp;int			bleft;int *			offset;int *			op;static int		lr_table [] = {0, 1, 1, 0};static int		dirp_table [] = {3, 2, 3, 2};	pts = rip -> pts;	n = pts -> n;	/* Compute the short leg candidate lists.  We save them in a	*/	/* dynamic buffer first.  Later we massage the data structure	*/	/* into something more appropriate for access.			*/	root = NULL;	hookp = &root;	bufp = NULL;	bleft = 0;	index = 0;	offset = NEWA (4 * (n + 1), int);	op = offset;	for (dir = 0; dir < 4; dir++) {		lr	= lr_table [dir];		dirp	= dirp_table [dir];		succ = rip -> succ [dir];		dir_off = DSTDIR_GETOFFSET (dir);		dir1_off = DSTDIR_GETOFFSET (dir + 1);		lrdir_off = LRINDEX_GETOFFSET (dir);		ub0 = rip -> ub0 [dir];		ub0p = rip -> ub0 [dirp];		p1 = &(pts -> a [0]);		for (i = 0; i < n; i++, p1++) {			*op++ = index;			limit = ub0 [i];			for (j = succ [i]; j >= 0; j = succ [j]) {				p2 = &(pts -> a [j]);				d1 = DSTDIR_OFFSET (p1, p2, dir_off);				if (d1 == 0.0) continue;				if (d1 > limit) break;				d2 = DSTDIR_OFFSET (p1, p2, dir1_off);				if (d2 EQ 0.0) break;				if (LRINDEX_OFFSET (p1, p2, lrdir_off) NE lr) {					continue;				}				if (d2 > ub0p [j]) continue;				b = bsd (rip -> bsd, i, j);				if (d1 > b) continue;				if (d2 > b) continue;				if (is_empty_rectangle (rip -> empty_rect, i, j)) {					/* j is a short leg candidate for i */					/* Store it away! */					if (bleft <= 0) {						ibp = (struct ibuf *)							new (offsetof (struct ibuf,								       buf [n]));						ibp -> next = NULL;						ibp -> count = 0;						*hookp = ibp;

⌨️ 快捷键说明

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