Actual source code: isdiff.c
1: #define PETSCVEC_DLL
3: #include petscis.h
4: #include petscbt.h
8: /*@
9: ISDifference - Computes the difference between two index sets.
11: Collective on IS
13: Input Parameter:
14: + is1 - first index, to have items removed from it
15: - is2 - index values to be removed
17: Output Parameters:
18: . isout - is1 - is2
20: Notes:
21: Negative values are removed from the lists. is2 may have values
22: that are not in is1. This requires O(imax-imin) memory and O(imax-imin)
23: work, where imin and imax are the bounds on the indices in is1.
25: Level: intermediate
27: Concepts: index sets^difference
28: Concepts: IS^difference
30: .seealso: ISDestroy(), ISView(), ISSum(), ISExpand()
32: @*/
33: PetscErrorCode ISDifference(IS is1,IS is2,IS *isout)
34: {
36: PetscInt i,n1,n2,imin,imax,nout,*iout;
37: const PetscInt *i1,*i2;
38: PetscBT mask;
39: MPI_Comm comm;
46: ISGetIndices(is1,&i1);
47: ISGetLocalSize(is1,&n1);
49: /* Create a bit mask array to contain required values */
50: if (n1) {
51: imin = PETSC_MAX_INT;
52: imax = 0;
53: for (i=0; i<n1; i++) {
54: if (i1[i] < 0) continue;
55: imin = PetscMin(imin,i1[i]);
56: imax = PetscMax(imax,i1[i]);
57: }
58: } else {
59: imin = imax = 0;
60: }
61: PetscBTCreate(imax-imin,mask);
62: /* Put the values from is1 */
63: for (i=0; i<n1; i++) {
64: if (i1[i] < 0) continue;
65: PetscBTSet(mask,i1[i] - imin);
66: }
67: ISRestoreIndices(is1,&i1);
68: /* Remove the values from is2 */
69: ISGetIndices(is2,&i2);
70: ISGetLocalSize(is2,&n2);
71: for (i=0; i<n2; i++) {
72: if (i2[i] < imin || i2[i] > imax) continue;
73: PetscBTClear(mask,i2[i] - imin);
74: }
75: ISRestoreIndices(is2,&i2);
76:
77: /* Count the number in the difference */
78: nout = 0;
79: for (i=0; i<imax-imin+1; i++) {
80: if (PetscBTLookup(mask,i)) nout++;
81: }
83: /* create the new IS containing the difference */
84: PetscMalloc(nout*sizeof(PetscInt),&iout);
85: nout = 0;
86: for (i=0; i<imax-imin+1; i++) {
87: if (PetscBTLookup(mask,i)) iout[nout++] = i + imin;
88: }
89: PetscObjectGetComm((PetscObject)is1,&comm);
90: ISCreateGeneralNC(comm,nout,iout,isout);
92: PetscBTDestroy(mask);
93: return(0);
94: }
98: /*@
99: ISSum - Computes the sum (union) of two index sets.
101: Only sequential version (at the moment)
103: Input Parameter:
104: + is1 - index set to be extended
105: - is2 - index values to be added
107: Output Parameter:
108: . is3 - the sum; this can not be is1 or is2
110: Notes:
111: If n1 and n2 are the sizes of the sets, this takes O(n1+n2) time;
113: Both index sets need to be sorted on input.
115: Level: intermediate
117: .seealso: ISDestroy(), ISView(), ISDifference(), ISExpand()
119: Concepts: index sets^union
120: Concepts: IS^union
122: @*/
123: PetscErrorCode ISSum(IS is1,IS is2,IS *is3)
124: {
125: MPI_Comm comm;
126: PetscTruth f;
127: PetscMPIInt size;
128: const PetscInt *i1,*i2;
129: PetscInt n1,n2,n3, p1,p2, *iout;
135: PetscObjectGetComm((PetscObject)(is1),&comm);
136: MPI_Comm_size(comm,&size);
137: if (size>1) SETERRQ(PETSC_ERR_SUP,"Currently only for uni-processor IS");
139: ISSorted(is1,&f);
140: if (!f) SETERRQ(PETSC_ERR_ARG_INCOMP,"Arg 1 is not sorted");
141: ISSorted(is2,&f);
142: if (!f) SETERRQ(PETSC_ERR_ARG_INCOMP,"Arg 2 is not sorted");
144: ISGetLocalSize(is1,&n1);
145: ISGetLocalSize(is2,&n2);
146: if (!n2) return(0);
147: ISGetIndices(is1,&i1);
148: ISGetIndices(is2,&i2);
150: p1 = 0; p2 = 0; n3 = 0;
151: do {
152: if (p1==n1) { /* cleanup for is2 */ n3 += n2-p2; break;
153: } else {
154: while (p2<n2 && i2[p2]<i1[p1]) {n3++; p2++;}
155: if (p2==n2) { /* cleanup for is1 */ n3 += n1-p1; break;
156: } else {
157: if (i2[p2]==i1[p1]) {n3++; p1++; p2++;}
158: }
159: }
160: if (p2==n2) { /* cleanup for is1 */ n3 += n1-p1; break;
161: } else {
162: while (p1<n1 && i1[p1]<i2[p2]) {n3++; p1++;}
163: if (p1==n1) { /* clean up for is2 */ n3 += n2-p2; break;
164: } else {
165: if (i1[p1]==i2[p2]) {n3++; p1++; p2++;}
166: }
167: }
168: } while (p1<n1 || p2<n2);
170: if (n3==n1) { /* no new elements to be added */
171: ISRestoreIndices(is1,&i1);
172: ISRestoreIndices(is2,&i2);
173: ISDuplicate(is1,is3);
174: return(0);
175: }
176: PetscMalloc(n3*sizeof(PetscInt),&iout);
178: p1 = 0; p2 = 0; n3 = 0;
179: do {
180: if (p1==n1) { /* cleanup for is2 */
181: while (p2<n2) iout[n3++] = i2[p2++];
182: break;
183: } else {
184: while (p2<n2 && i2[p2]<i1[p1]) iout[n3++] = i2[p2++];
185: if (p2==n2) { /* cleanup for is1 */
186: while (p1<n1) iout[n3++] = i1[p1++];
187: break;
188: } else {
189: if (i2[p2]==i1[p1]) {iout[n3++] = i1[p1++]; p2++;}
190: }
191: }
192: if (p2==n2) { /* cleanup for is1 */
193: while (p1<n1) iout[n3++] = i1[p1++];
194: break;
195: } else {
196: while (p1<n1 && i1[p1]<i2[p2]) iout[n3++] = i1[p1++];
197: if (p1==n1) { /* clean up for is2 */
198: while (p2<n2) iout[n3++] = i2[p2++];
199: break;
200: } else {
201: if (i1[p1]==i2[p2]) {iout[n3++] = i1[p1++]; p2++;}
202: }
203: }
204: } while (p1<n1 || p2<n2);
206: ISRestoreIndices(is1,&i1);
207: ISRestoreIndices(is2,&i2);
208: ISCreateGeneral(comm,n3,iout,is3);
209: PetscFree(iout);
210: return(0);
211: }
215: /*@
216: ISExpand - Computes the union of two index sets, by concatenating 2 lists and
217: removing duplicates.
219: Collective on IS
221: Input Parameter:
222: + is1 - first index set
223: - is2 - index values to be added
225: Output Parameters:
226: . isout - is1 + is2 The index set is2 is appended to is1 removing duplicates
228: Notes:
229: Negative values are removed from the lists. This requires O(imax-imin)
230: memory and O(imax-imin) work, where imin and imax are the bounds on the
231: indices in is1 and is2.
233: The IS's do not need to be sorted.
235: Level: intermediate
237: .seealso: ISDestroy(), ISView(), ISDifference(), ISSum()
239: Concepts: index sets^difference
240: Concepts: IS^difference
242: @*/
243: PetscErrorCode ISExpand(IS is1,IS is2,IS *isout)
244: {
246: PetscInt i,n1,n2,imin,imax,nout,*iout;
247: const PetscInt *i1,*i2;
248: PetscBT mask;
249: MPI_Comm comm;
256: ISGetIndices(is1,&i1);
257: ISGetLocalSize(is1,&n1);
258: ISGetIndices(is2,&i2);
259: ISGetLocalSize(is2,&n2);
261: /* Create a bit mask array to contain required values */
262: if (n1 || n2) {
263: imin = PETSC_MAX_INT;
264: imax = 0;
265: for (i=0; i<n1; i++) {
266: if (i1[i] < 0) continue;
267: imin = PetscMin(imin,i1[i]);
268: imax = PetscMax(imax,i1[i]);
269: }
270: for (i=0; i<n2; i++) {
271: if (i2[i] < 0) continue;
272: imin = PetscMin(imin,i2[i]);
273: imax = PetscMax(imax,i2[i]);
274: }
275: } else {
276: imin = imax = 0;
277: }
278: PetscMalloc((n1+n2)*sizeof(PetscInt),&iout);
279: nout = 0;
280: PetscBTCreate(imax-imin,mask);
281: /* Put the values from is1 */
282: for (i=0; i<n1; i++) {
283: if (i1[i] < 0) continue;
284: if (!PetscBTLookupSet(mask,i1[i] - imin)) {
285: iout[nout++] = i1[i];
286: }
287: }
288: ISRestoreIndices(is1,&i1);
289: /* Put the values from is2 */
290: for (i=0; i<n2; i++) {
291: if (i2[i] < 0) continue;
292: if (!PetscBTLookupSet(mask,i2[i] - imin)) {
293: iout[nout++] = i2[i];
294: }
295: }
296: ISRestoreIndices(is2,&i2);
298: /* create the new IS containing the sum */
299: PetscObjectGetComm((PetscObject)is1,&comm);
300: ISCreateGeneral(comm,nout,iout,isout);
301: PetscFree(iout);
303: PetscBTDestroy(mask);
304: return(0);
305: }