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