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,*i1,*i2,n1,n2,imin,imax,nout,*iout;
37: PetscBT mask;
38: MPI_Comm comm;
45: ISGetIndices(is1,&i1);
46: ISGetLocalSize(is1,&n1);
48: /* Create a bit mask array to contain required values */
49: if (n1) {
50: imin = PETSC_MAX_INT;
51: imax = 0;
52: for (i=0; i<n1; i++) {
53: if (i1[i] < 0) continue;
54: imin = PetscMin(imin,i1[i]);
55: imax = PetscMax(imax,i1[i]);
56: }
57: } else {
58: imin = imax = 0;
59: }
60: PetscBTCreate(imax-imin,mask);
61: /* Put the values from is1 */
62: for (i=0; i<n1; i++) {
63: if (i1[i] < 0) continue;
64: PetscBTSet(mask,i1[i] - imin);
65: }
66: ISRestoreIndices(is1,&i1);
67: /* Remove the values from is2 */
68: ISGetIndices(is2,&i2);
69: ISGetLocalSize(is2,&n2);
70: for (i=0; i<n2; i++) {
71: if (i2[i] < imin || i2[i] > imax) continue;
72: PetscBTClear(mask,i2[i] - imin);
73: }
74: ISRestoreIndices(is2,&i2);
75:
76: /* Count the number in the difference */
77: nout = 0;
78: for (i=0; i<imax-imin+1; i++) {
79: if (PetscBTLookup(mask,i)) nout++;
80: }
82: /* create the new IS containing the difference */
83: PetscMalloc(nout*sizeof(PetscInt),&iout);
84: nout = 0;
85: for (i=0; i<imax-imin+1; i++) {
86: if (PetscBTLookup(mask,i)) iout[nout++] = i + imin;
87: }
88: PetscObjectGetComm((PetscObject)is1,&comm);
89: ISCreateGeneralNC(comm,nout,iout,isout);
91: PetscBTDestroy(mask);
92: return(0);
93: }
97: /*@
98: ISSum - Computes the sum (union) of two index sets.
100: Only sequential version (at the moment)
102: Input Parameter:
103: + is1 - index set to be extended
104: - is2 - index values to be added
106: Output Parameter:
107: . is3 - the sum; this can not be is1 or is2
109: Notes:
110: If n1 and n2 are the sizes of the sets, this takes O(n1+n2) time;
112: Both index sets need to be sorted on input.
114: Level: intermediate
116: .seealso: ISDestroy(), ISView(), ISDifference(), ISExpand()
118: Concepts: index sets^union
119: Concepts: IS^union
121: @*/
122: PetscErrorCode ISSum(IS is1,IS is2,IS *is3)
123: {
124: MPI_Comm comm;
125: PetscTruth f;
126: PetscMPIInt size;
127: PetscInt *i1,*i2,n1,n2,n3, p1,p2, *iout;
133: PetscObjectGetComm((PetscObject)(is1),&comm);
134: MPI_Comm_size(comm,&size);
135: if (size>1) SETERRQ(PETSC_ERR_SUP,"Currently only for uni-processor IS");
137: ISSorted(is1,&f);
138: if (!f) SETERRQ(PETSC_ERR_ARG_INCOMP,"Arg 1 is not sorted");
139: ISSorted(is2,&f);
140: if (!f) SETERRQ(PETSC_ERR_ARG_INCOMP,"Arg 2 is not sorted");
142: ISGetLocalSize(is1,&n1);
143: ISGetLocalSize(is2,&n2);
144: if (!n2) return(0);
145: ISGetIndices(is1,&i1);
146: ISGetIndices(is2,&i2);
148: p1 = 0; p2 = 0; n3 = 0;
149: do {
150: if (p1==n1) { /* cleanup for is2 */ n3 += n2-p2; break;
151: } else {
152: while (p2<n2 && i2[p2]<i1[p1]) {n3++; p2++;}
153: if (p2==n2) { /* cleanup for is1 */ n3 += n1-p1; break;
154: } else {
155: if (i2[p2]==i1[p1]) {n3++; p1++; p2++;}
156: }
157: }
158: if (p2==n2) { /* cleanup for is1 */ n3 += n1-p1; break;
159: } else {
160: while (p1<n1 && i1[p1]<i2[p2]) {n3++; p1++;}
161: if (p1==n1) { /* clean up for is2 */ n3 += n2-p2; break;
162: } else {
163: if (i1[p1]==i2[p2]) {n3++; p1++; p2++;}
164: }
165: }
166: } while (p1<n1 || p2<n2);
168: if (n3==n1) { /* no new elements to be added */
169: ISRestoreIndices(is1,&i1);
170: ISRestoreIndices(is2,&i2);
171: ISDuplicate(is1,is3);
172: return(0);
173: }
174: PetscMalloc(n3*sizeof(PetscInt),&iout);
176: p1 = 0; p2 = 0; n3 = 0;
177: do {
178: if (p1==n1) { /* cleanup for is2 */
179: while (p2<n2) iout[n3++] = i2[p2++];
180: break;
181: } else {
182: while (p2<n2 && i2[p2]<i1[p1]) iout[n3++] = i2[p2++];
183: if (p2==n2) { /* cleanup for is1 */
184: while (p1<n1) iout[n3++] = i1[p1++];
185: break;
186: } else {
187: if (i2[p2]==i1[p1]) {iout[n3++] = i1[p1++]; p2++;}
188: }
189: }
190: if (p2==n2) { /* cleanup for is1 */
191: while (p1<n1) iout[n3++] = i1[p1++];
192: break;
193: } else {
194: while (p1<n1 && i1[p1]<i2[p2]) iout[n3++] = i1[p1++];
195: if (p1==n1) { /* clean up for is2 */
196: while (p2<n2) iout[n3++] = i2[p2++];
197: break;
198: } else {
199: if (i1[p1]==i2[p2]) {iout[n3++] = i1[p1++]; p2++;}
200: }
201: }
202: } while (p1<n1 || p2<n2);
204: ISRestoreIndices(is1,&i1);
205: ISRestoreIndices(is2,&i2);
206: ISCreateGeneral(comm,n3,iout,is3);
207: PetscFree(iout);
208: return(0);
209: }
213: /*@
214: ISExpand - Computes the union of two index sets, by concatenating 2 lists and
215: removing duplicates.
217: Collective on IS
219: Input Parameter:
220: + is1 - first index set
221: - is2 - index values to be added
223: Output Parameters:
224: . isout - is1 + is2 The index set is2 is appended to is1 removing duplicates
226: Notes:
227: Negative values are removed from the lists. This requires O(imax-imin)
228: memory and O(imax-imin) work, where imin and imax are the bounds on the
229: indices in is1 and is2.
231: The IS's do not need to be sorted.
233: Level: intermediate
235: .seealso: ISDestroy(), ISView(), ISDifference(), ISSum()
237: Concepts: index sets^difference
238: Concepts: IS^difference
240: @*/
241: PetscErrorCode ISExpand(IS is1,IS is2,IS *isout)
242: {
244: PetscInt i,*i1,*i2,n1,n2,imin,imax,nout,*iout;
245: PetscBT mask;
246: MPI_Comm comm;
253: ISGetIndices(is1,&i1);
254: ISGetLocalSize(is1,&n1);
255: ISGetIndices(is2,&i2);
256: ISGetLocalSize(is2,&n2);
258: /* Create a bit mask array to contain required values */
259: if (n1 || n2) {
260: imin = PETSC_MAX_INT;
261: imax = 0;
262: for (i=0; i<n1; i++) {
263: if (i1[i] < 0) continue;
264: imin = PetscMin(imin,i1[i]);
265: imax = PetscMax(imax,i1[i]);
266: }
267: for (i=0; i<n2; i++) {
268: if (i2[i] < 0) continue;
269: imin = PetscMin(imin,i2[i]);
270: imax = PetscMax(imax,i2[i]);
271: }
272: } else {
273: imin = imax = 0;
274: }
275: PetscMalloc((n1+n2)*sizeof(PetscInt),&iout);
276: nout = 0;
277: PetscBTCreate(imax-imin,mask);
278: /* Put the values from is1 */
279: for (i=0; i<n1; i++) {
280: if (i1[i] < 0) continue;
281: if (!PetscBTLookupSet(mask,i1[i] - imin)) {
282: iout[nout++] = i1[i];
283: }
284: }
285: ISRestoreIndices(is1,&i1);
286: /* Put the values from is2 */
287: for (i=0; i<n2; i++) {
288: if (i2[i] < 0) continue;
289: if (!PetscBTLookupSet(mask,i2[i] - imin)) {
290: iout[nout++] = i2[i];
291: }
292: }
293: ISRestoreIndices(is2,&i2);
295: /* create the new IS containing the sum */
296: PetscObjectGetComm((PetscObject)is1,&comm);
297: ISCreateGeneral(comm,nout,iout,isout);
298: PetscFree(iout);
300: PetscBTDestroy(mask);
301: return(0);
302: }