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

📄 efst.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 5 页
字号:
			" [-v N]"			" <points-file\n",			me);	pp = &arg_doc [0];	while ((p = *pp++) NE NULL) {		(void) fprintf (stderr, "%s\n", p);	}	exit (1);}/* * Use the heapsort algorithm to sort the given terminals in increasing * order by the following keys: * *	1.	X coordinate *	2.	Y coordinate *	3.	index (i.e., position within input data) * * Of course, we do not move the points, but rather permute an array * of indexes into the points. */	static	int *heapsort_x (struct pset *		pts		/* IN - the terminals to sort */){int			i, i1, i2, j, k, n;struct point *		p1;struct point *		p2;int *			index;	n = pts -> n;	index = NEWA (n, int);	for (i = 0; i < n; i++) {		index [i] = i;	}	/* Construct the heap via sift-downs, in O(n) time. */	for (k = n >> 1; k >= 0; k--) {		j = k;		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 -> x > p1 -> x) OR				    ((p2 -> x EQ p1 -> x) AND				     ((p2 -> y > p1 -> y) OR				      ((p2 -> y EQ p1 -> y) 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 -> x > p2 -> x) OR			    ((p1 -> x EQ p2 -> x) AND			     ((p1 -> y > p2 -> y) OR			      ((p1 -> y EQ p2 -> y) 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 -> x > p1 -> x) OR				    ((p2 -> x EQ p1 -> x) AND				     ((p2 -> y > p1 -> y) OR				      ((p2 -> y EQ p1 -> y) 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 -> x > p2 -> x) OR			    ((p1 -> x EQ p2 -> x) AND			     ((p1 -> y > p2 -> y) OR			      ((p1 -> y EQ p2 -> y) 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);	ZERO_PSET (newpts, 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);}/* Solve a quadratic equation of the form * A/2 X^2 + B X + C/2 = 0 * * We use a numerically robust formula from Press et al: Numerical * Recipies. * Only solves the equation if A <> 0. * Return FALSE if there are no real roots. */	static	boolsolve_quadratic (double	 A,	 /* IN - twice the first coefficient */double	 B,	 /* IN - second coefficient */double	 C,	 /* IN - twice the third coefficient */double * root1,	 /* OUT - first root */double * root2	 /* OUT - second root */){	double Q, D;	if (A EQ 0.0) return FALSE; /* this is not a quadratic equation */	D = B*B - A*C;	if (D < 0.0)  return FALSE; /* no real roots */	D = sqrt(D);	if (B >= 0.0)		Q = - B - D;	else		Q = - B + D;	if (Q NE 0.0) {		*root1 = Q / A;		*root2 = C / Q;	}	else {		*root1 = 0.0;		*root2 = -2.0 * B / A;	}	return TRUE;}/* * Upper bound heuristic (just calls the heuristic that was chosen) */	static	dist_tupper_bound_heuristic (struct pset *	pts,	/* IN - point set */struct bsd  *	bsdp	/* IN - BSD info (can be NULL) */){	if (NOT Use_Greedy_Heuristic) {		return smith_lee_liebman (pts, bsdp);	}	else {		return greedy_heuristic	 (pts, bsdp);	}}/* * Test if a new value of LP leads to a pruning of the eq-point. * If not then update LP. * First move the new point slightly to the left in order to * avoid (too many) numerical difficulties. */	static	booltest_and_save_LP (struct einfo *	eip,	/* IN - global EFST info */struct eqp_t *	eqpi,	/* IN - first eq-point */struct eqp_t *	eqpj,	/* IN - second eq-point */struct eqp_t *	eqpk,	/* IN/OUT - new eq-point */struct point *	CLP	/* IN - new proposed LP point */){struct point NLP;struct point PLP;	/* First check that the new point is between eqpk -> LP and eqpi -> E */	if ((CLP -> x EQ eqpi -> E.x) AND (CLP -> y EQ eqpi -> E.y)) return TRUE;	if (right_turn(&(eqpk -> E), &(eqpi -> E),  CLP))	     return TRUE;	if (left_turn (&(eqpk -> E), &(eqpk -> LP), CLP))	     return TRUE;	memset (&PLP, 0, sizeof (PLP));	memset (&NLP, 0, sizeof (NLP));	/* Now move it a little closer to eqpj -> E, just to be on the safe side */	PLP.x = CLP -> x + (eqpj -> E.x - CLP -> x) * eip -> eps * ((double) eqpk -> S);	PLP.y = CLP -> y + (eqpj -> E.y - CLP -> y) * eip -> eps * ((double) eqpk -> S);	project_point(&(eqpk -> E), &(eqpk -> DC), &PLP, &NLP);	/* We pass eqpk -> LP? */	if (left_turn (&(eqpk -> E), &(eqpk -> LP), &NLP))	     return TRUE;	/* Now make the actual testing */	if (right_turn(&(eqpk -> E), &(eqpk -> RP), &NLP))	     return FALSE;	eqpk -> LP = NLP;	return TRUE;}/* * Test if a new value of RP leads to a pruning of the eq-point. * If not then update RP. * First move the new point slightly to the right in order to * avoid (too many) numerical difficulties. */	static	booltest_and_save_RP (struct einfo *	eip,	/* IN - global EFST info */struct eqp_t *	eqpi,	/* IN - first eq-point */struct eqp_t *	eqpj,	/* IN - second eq-point */struct eqp_t *	eqpk,	/* IN/OUT - new eq-point */struct point *	CRP	/* IN - new proposed RP point */){struct point NRP;struct point PRP;	/* First check that the new point is between eqpj -> E and eqpk -> RP */	if ((CRP -> x EQ eqpj -> E.x) AND (CRP -> y EQ eqpj -> E.y)) return TRUE;	if (left_turn (&(eqpk -> E), &(eqpj -> E),  CRP))	     return TRUE;	if (right_turn(&(eqpk -> E), &(eqpk -> RP), CRP))	     return TRUE;	memset (&PRP, 0, sizeof (PRP));	memset (&NRP, 0, sizeof (NRP));	/* Now move it a little closer to eqpi -> E, just to be on the safe side */	PRP.x = CRP -> x + (eqpi -> E.x - CRP -> x) * eip -> eps * ((double) eqpk -> S);	PRP.y = CRP -> y + (eqpi -> E.y - CRP -> y) * eip -> eps * ((double) eqpk -> S);	project_point(&(eqpk -> E), &(eqpk -> DC), &PRP, &NRP);	/* We pass eqpk -> RP? */	if (right_turn (&(eqpk -> E), &(eqpk -> RP), &NRP))	     return TRUE;	/* Now make the actual testing */	if (left_turn(&(eqpk -> E), &(eqpk -> LP), &NRP))	     return FALSE;	eqpk -> RP = NRP;	return TRUE;}/* * Flag all terminals involved in eq-point k */	static	voidset_member_arr (struct einfo * eip,  /* IN/OUT - global EFST info */struct eqp_t * eqp,  /* IN - eq-point */bool flag	     /* IN - value of flag */){	eterm_t *p    = eqp -> Z;	eterm_t *endp = p + eqp -> S;	while (p < endp) {		int t = *p++;		eip -> MEMB [t] = flag;	}}/*

⌨️ 快捷键说明

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