1 #include "BSprivate.h"
2 
3 /*+ BSperm_rows - Permute the nonzeros in A in preparation for
4                   creating the efficient parallel execution structure
5 
6     Input Parameters:
7 .   A - the sparse matrix
8 .   gnum - the new global numbering of the rows
9 .   perm - the inode permutation
10 .   distr - the inode distribution
11 .   procinfo - the usual processor stuff
12 .   keep - Indicates if certain structures should be kept for future
13            permuting of this structure
14 .   max_row_len - the maximum length of any row in A
15 
16     Output Parameters:
17 .   A - the sparse matrix with permuted rows
18 
19     Returns:
20     a structure used to perform the permutation quickly in the future
21 
22  +*/
BSperm_rows(BSspmat * A,BSnumbering * gnum,BSpermutation * perm,BSdistribution * distr,BSprocinfo * procinfo,int keep,int * max_row_len)23 BSkey_arr *BSperm_rows(BSspmat *A, BSnumbering *gnum, BSpermutation *perm,
24 	BSdistribution *distr, BSprocinfo *procinfo, int keep, int *max_row_len)
25 {
26 	int	num_nz;
27 	int	count, ind;
28 	int	i, j, k;
29 	BSpermutation *iperm;
30 	BSpermutation *tperm;
31 	int	*key;
32 	BSkey_arr *key_arr;
33 	FLOAT	*dwork;
34 	int	*iwork;
35 	BSbb *trans_bb;
36 	int	query_len, *addrs, *answs;
37 	void    (*map)(int,int *,int *,BSprocinfo *,BSmapping *);
38 	BSsprow *row;
39 	int	*colptr;
40 	FLOAT	*nzptr;
41 	int	*map_work;
42 
43 
44 	/* create inverse permutation */
45 	iperm = BSalloc_permutation(A->num_rows); CHKERRN(0);
46 	BSperm2iperm(perm,iperm); CHKERRN(0);
47 
48 	/* find the number of nonlocal nonzeros */
49 	num_nz = BSnonlocalnz(A,max_row_len,procinfo); CHKERRN(0);
50 	MY_MALLOCN(map_work,(int *),sizeof(int)*(*max_row_len),0);
51 
52 	/* set up query */
53 	map = A->map->fglobal2proc;
54 	MY_MALLOCN(addrs,(int *),sizeof(int)*num_nz,3);
55 	query_len = 0;
56 	count = 0;
57 	for (i=0;i<distr->max+1;i++) {
58 		ind = iperm->perm[count];
59 		count += distr->distribution[i];
60 		row = A->rows[ind];
61 		colptr = row->col;
62 		(*map)(row->length,colptr,map_work,procinfo,A->map); CHKERRN(0);
63 		for (j=0;j<row->length;j++) {
64 			if (map_work[j] != procinfo->my_id) {
65 				addrs[query_len] = colptr[j];
66 				query_len++;
67 			}
68 		}
69 	}
70 
71 	/* set up and query bulletin board */
72 	trans_bb = BSinit_bb(A->num_rows,A->map);CHKERRN(0);
73 	BSpost_noaddr_bb(trans_bb,A->num_rows,gnum->numbers); CHKERRN(0);
74 	MY_MALLOCN(answs,(int *),sizeof(int)*num_nz,4);
75 	BSquery_match_bb(trans_bb,query_len,addrs,answs,procinfo); CHKERRN(0);
76 	MY_FREEN(addrs);
77 	BSfree_bb(trans_bb); CHKERRN(0);
78 
79 	/* now, do the sorting */
80 	MY_MALLOCN(dwork,(FLOAT *),sizeof(FLOAT)*(*max_row_len),1);
81 	MY_MALLOCN(iwork,(int *),sizeof(int)*(*max_row_len),2);
82 	/* if keep is true, then allocate array of keys */
83 	if (keep) {
84 		key_arr = BSalloc_key_arr(distr->max+1); CHKERRN(0);
85 	} else {
86 		key_arr = NULL;
87 		MY_MALLOCN(key,(int *),sizeof(int)*(*max_row_len),5);
88 	}
89 	query_len = 0;
90 	count = 0;
91 	map = A->map->fglobal2local;
92 	tperm = BSalloc_permutation((*max_row_len)); CHKERRN(0);
93 	for (i=0;i<distr->max+1;i++) {
94 		ind = iperm->perm[count];
95 		row = A->rows[ind];
96 		colptr = row->col;
97 		if (keep) {
98 			MY_MALLOCN(key,(int *),sizeof(int)*row->length,5);
99 			key_arr->array[i] = key;
100 		}
101 		(*map)(row->length,colptr,map_work,procinfo,A->map); CHKERRN(0);
102 		for (j=0;j<row->length;j++) {
103 			if (map_work[j] < 0) {
104 				key[j] = answs[query_len];
105 				query_len++;
106 			} else {
107 				key[j] = gnum->numbers[map_work[j]];
108 			}
109 		}
110 		BSreset_permutation(row->length,tperm); CHKERRN(0);
111 		for (j=0;j<row->length;j++) tperm->perm[j] = j;
112 
113 		/* now find the inverse permutation according to the new numbers */
114 		BSheap_sort1(row->length,key,tperm->perm); CHKERRN(0);
115 
116 		/* permute the column values into iwork and then copy them */
117 		/* into the correct places */
118 		/* also create a floating point work vector */
119 		BSiperm_ivec(colptr,iwork,tperm); CHKERRN(0);
120 		for (k=0;k<row->length;k++) {
121 			colptr[k] = iwork[k];
122 		}
123 		for (j=0;j<distr->distribution[i];j++) {
124 			ind = iperm->perm[count];
125 			row = A->rows[ind];
126 			nzptr = row->nz;
127 			BSiperm_dvec(nzptr,dwork,tperm); CHKERRN(0);
128 			for (k=0;k<row->length;k++) {
129 				nzptr[k] = dwork[k];
130 			}
131 			count++;
132 		}
133 	}
134 	BSfree_permutation(tperm); CHKERRN(0);
135 
136 	if (!keep) {
137 		MY_FREE(key);
138 	}
139 	MY_FREEN(map_work);
140 	MY_FREEN(dwork);
141 	MY_FREEN(iwork);
142 	MY_FREEN(answs);
143 	BSfree_permutation(iperm); CHKERRN(0);
144 
145 	return(key_arr);
146 }
147