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: }