xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1 #include <../src/sys/classes/draw/utils/axisimpl.h>  /*I   "petscdraw.h"  I*/
2 
3 PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
4 
5 /*@
6    PetscDrawAxisCreate - Generate the axis data structure.
7 
8    Collective on PetscDraw
9 
10    Input Parameters:
11 .  win - PetscDraw object where axis to to be made
12 
13    Ouput Parameters:
14 .  axis - the axis datastructure
15 
16    Notes: the MPI communicator that owns the underlying draw object owns the PetscDrawAxis object, but calls to set PetscDrawAxis options are ignored by all processes
17           except the first MPI process in the communicator
18 
19    Level: advanced
20 
21 .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawSPCreate(), PetscDrawSP, PetscDrawHGCreate(), PetscDrawHG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawLGGetAxis(), PetscDrawSPGetAxis(),
22           PetscDrawHGGetAxis(), PetscDrawBarGetAxis(), PetscDrawAxis, PetscDrawAxisDestroy(), PetscDrawAxisSetColors(), PetscDrawAxisSetLabels(), PetscDrawAxisSetLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetHoldLimits(),
23           PetscDrawAxisDraw()
24 @*/
25 PetscErrorCode  PetscDrawAxisCreate(PetscDraw draw,PetscDrawAxis *axis)
26 {
27   PetscDrawAxis  ad;
28   PetscErrorCode ierr;
29 
30   PetscFunctionBegin;
31   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
32   PetscValidPointer(axis,2);
33 
34   ierr = PetscHeaderCreate(ad,PETSC_DRAWAXIS_CLASSID,"DrawAxis","Draw Axis","Draw",PetscObjectComm((PetscObject)draw),PetscDrawAxisDestroy,NULL);CHKERRQ(ierr);
35   ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)ad);CHKERRQ(ierr);
36 
37   ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr);
38   ad->win = draw;
39 
40   ad->xticks    = PetscADefTicks;
41   ad->yticks    = PetscADefTicks;
42   ad->xlabelstr = PetscADefLabel;
43   ad->ylabelstr = PetscADefLabel;
44   ad->ac        = PETSC_DRAW_BLACK;
45   ad->tc        = PETSC_DRAW_BLACK;
46   ad->cc        = PETSC_DRAW_BLACK;
47   ad->xlabel    = NULL;
48   ad->ylabel    = NULL;
49   ad->toplabel  = NULL;
50 
51   *axis = ad;
52   PetscFunctionReturn(0);
53 }
54 
55 /*@
56     PetscDrawAxisDestroy - Frees the space used by an axis structure.
57 
58     Collective on PetscDrawAxis
59 
60     Input Parameters:
61 .   axis - the axis context
62 
63     Level: advanced
64 
65 .seealso: PetscDrawAxisCreate(), PetscDrawAxis
66 @*/
67 PetscErrorCode  PetscDrawAxisDestroy(PetscDrawAxis *axis)
68 {
69   PetscErrorCode ierr;
70 
71   PetscFunctionBegin;
72   if (!*axis) PetscFunctionReturn(0);
73   PetscValidHeaderSpecific(*axis,PETSC_DRAWAXIS_CLASSID,1);
74   if (--((PetscObject)(*axis))->refct > 0) {*axis = NULL; PetscFunctionReturn(0);}
75 
76   ierr = PetscFree((*axis)->toplabel);CHKERRQ(ierr);
77   ierr = PetscFree((*axis)->xlabel);CHKERRQ(ierr);
78   ierr = PetscFree((*axis)->ylabel);CHKERRQ(ierr);
79   ierr = PetscDrawDestroy(&(*axis)->win);CHKERRQ(ierr);
80   ierr = PetscHeaderDestroy(axis);CHKERRQ(ierr);
81   PetscFunctionReturn(0);
82 }
83 
84 /*@
85     PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
86                          tickmarks, and text.
87 
88     Logically Collective on PetscDrawAxis
89 
90     Input Parameters:
91 +   axis - the axis
92 .   ac - the color of the axis lines
93 .   tc - the color of the tick marks
94 -   cc - the color of the text strings
95 
96     Level: advanced
97 
98 .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetLabels(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
99 @*/
100 PetscErrorCode  PetscDrawAxisSetColors(PetscDrawAxis axis,int ac,int tc,int cc)
101 {
102   PetscFunctionBegin;
103   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
104   PetscValidLogicalCollectiveInt(axis,ac,2);
105   PetscValidLogicalCollectiveInt(axis,tc,3);
106   PetscValidLogicalCollectiveInt(axis,cc,4);
107   axis->ac = ac; axis->tc = tc; axis->cc = cc;
108   PetscFunctionReturn(0);
109 }
110 
111 /*@C
112     PetscDrawAxisSetLabels -  Sets the x and y axis labels.
113 
114     Logically Collective on PetscDrawAxis
115 
116     Input Parameters:
117 +   axis - the axis
118 .   top - the label at the top of the image
119 -   xlabel,ylabel - the labes for the x and y axis
120 
121     Notes: Must be called before PetscDrawAxisDraw() or PetscDrawLGDraw()
122            There should be no newlines in the arguments
123 
124     Level: advanced
125 
126 .seealso: PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetColors(), PetscDrawAxisDraw(), PetscDrawAxisSetLimits()
127 @*/
128 PetscErrorCode  PetscDrawAxisSetLabels(PetscDrawAxis axis,const char top[],const char xlabel[],const char ylabel[])
129 {
130   PetscErrorCode ierr;
131 
132   PetscFunctionBegin;
133   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
134   ierr = PetscFree(axis->xlabel);CHKERRQ(ierr);
135   ierr = PetscFree(axis->ylabel);CHKERRQ(ierr);
136   ierr = PetscFree(axis->toplabel);CHKERRQ(ierr);
137   ierr = PetscStrallocpy(xlabel,&axis->xlabel);CHKERRQ(ierr);
138   ierr = PetscStrallocpy(ylabel,&axis->ylabel);CHKERRQ(ierr);
139   ierr = PetscStrallocpy(top,&axis->toplabel);CHKERRQ(ierr);
140   PetscFunctionReturn(0);
141 }
142 
143 /*@
144     PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
145 
146     Logically Collective on PetscDrawAxis
147 
148     Input Parameters:
149 +   axis - the axis
150 .   xmin,xmax - limits in x
151 -   ymin,ymax - limits in y
152 
153     Options Database:
154 .   -drawaxis_hold - hold the initial set of axis limits for future plotting
155 
156     Level: advanced
157 
158 .seealso:  PetscDrawAxisSetHoldLimits(), PetscDrawAxisGetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
159 
160 @*/
161 PetscErrorCode  PetscDrawAxisSetLimits(PetscDrawAxis axis,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax)
162 {
163   PetscErrorCode ierr;
164 
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
167   if (axis->hold) PetscFunctionReturn(0);
168   axis->xlow = xmin;
169   axis->xhigh= xmax;
170   axis->ylow = ymin;
171   axis->yhigh= ymax;
172   ierr = PetscOptionsHasName(((PetscObject)axis)->options,((PetscObject)axis)->prefix,"-drawaxis_hold",&axis->hold);CHKERRQ(ierr);
173   PetscFunctionReturn(0);
174 }
175 
176 /*@
177     PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
178 
179     Not Collective
180 
181     Input Parameters:
182 +   axis - the axis
183 .   xmin,xmax - limits in x
184 -   ymin,ymax - limits in y
185 
186     Level: advanced
187 
188 .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisSetHoldLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
189 
190 @*/
191 PetscErrorCode  PetscDrawAxisGetLimits(PetscDrawAxis axis,PetscReal *xmin,PetscReal *xmax,PetscReal *ymin,PetscReal *ymax)
192 {
193   PetscFunctionBegin;
194   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
195   *xmin = axis->xlow;
196   *xmax = axis->xhigh;
197   *ymin = axis->ylow;
198   *ymax = axis->yhigh;
199   PetscFunctionReturn(0);
200 }
201 
202 /*@
203     PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
204         again
205 
206     Logically Collective on PetscDrawAxis
207 
208     Input Parameters:
209 +   axis - the axis
210 -   hold - PETSC_TRUE - hold current limits, PETSC_FALSE allow limits to be changed
211 
212     Level: advanced
213 
214     Notes:
215         Once this has been called with PETSC_TRUE the limits will not change if you call
216      PetscDrawAxisSetLimits() until you call this with PETSC_FALSE
217 
218 .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
219 
220 @*/
221 PetscErrorCode  PetscDrawAxisSetHoldLimits(PetscDrawAxis axis,PetscBool hold)
222 {
223   PetscFunctionBegin;
224   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
225   PetscValidLogicalCollectiveBool(axis,hold,2);
226   axis->hold = hold;
227   PetscFunctionReturn(0);
228 }
229 
230 /*@
231     PetscDrawAxisDraw - PetscDraws an axis.
232 
233     Collective on PetscDrawAxis
234 
235     Input Parameter:
236 .   axis - Axis structure
237 
238     Level: advanced
239 
240     Note:
241     This draws the actual axis.  The limits etc have already been set.
242     By picking special routines for the ticks and labels, special
243     effects may be generated.  These routines are part of the Axis
244     structure (axis).
245 
246 .seealso:  PetscDrawAxisCreate(), PetscDrawAxis, PetscDrawAxisGetLimits(), PetscDrawAxisSetLimits(), PetscDrawAxisSetLabels(), PetscDrawAxisSetColors()
247 
248 @*/
249 PetscErrorCode  PetscDrawAxisDraw(PetscDrawAxis axis)
250 {
251   int            i,ntick,numx,numy,ac,tc,cc;
252   PetscMPIInt    rank;
253   size_t         len,ytlen=0;
254   PetscReal      coors[4],tickloc[MAXSEGS],sep,tw,th;
255   PetscReal      xl,xr,yl,yr,dxl=0,dyl=0,dxr=0,dyr=0;
256   char           *p;
257   PetscDraw      draw;
258   PetscBool      isnull;
259   PetscErrorCode ierr;
260 
261   PetscFunctionBegin;
262   PetscValidHeaderSpecific(axis,PETSC_DRAWAXIS_CLASSID,1);
263   ierr = PetscDrawIsNull(axis->win,&isnull);CHKERRQ(ierr);
264   if (isnull) PetscFunctionReturn(0);
265   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)axis),&rank);CHKERRQ(ierr);
266 
267   draw = axis->win;
268 
269   ac = axis->ac; tc = axis->tc; cc = axis->cc;
270   if (axis->xlow == axis->xhigh) {axis->xlow -= .5; axis->xhigh += .5;}
271   if (axis->ylow == axis->yhigh) {axis->ylow -= .5; axis->yhigh += .5;}
272 
273   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
274   if (rank) goto finally;
275 
276   /* get cannonical string size */
277   ierr = PetscDrawSetCoordinates(draw,0,0,1,1);CHKERRQ(ierr);
278   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
279   /* lower spacing */
280   if (axis->xlabelstr) dyl += 1.5*th;
281   if (axis->xlabel)    dyl += 1.5*th;
282   /* left spacing */
283   if (axis->ylabelstr) dxl += 7.5*tw;
284   if (axis->ylabel)    dxl += 2.0*tw;
285   /* right and top spacing */
286   if (axis->xlabelstr) dxr = 2.5*tw;
287   if (axis->ylabelstr) dyr = 0.5*th;
288   if (axis->toplabel)  dyr = 1.5*th;
289   /* extra spacing */
290   dxl += 0.7*tw; dxr += 0.5*tw;
291   dyl += 0.2*th; dyr += 0.2*th;
292   /* determine coordinates */
293   xl = (dxl*axis->xhigh + dxr*axis->xlow - axis->xlow)  / (dxl + dxr - 1);
294   xr = (dxl*axis->xhigh + dxr*axis->xlow - axis->xhigh) / (dxl + dxr - 1);
295   yl = (dyl*axis->yhigh + dyr*axis->ylow - axis->ylow)  / (dyl + dyr - 1);
296   yr = (dyl*axis->yhigh + dyr*axis->ylow - axis->yhigh) / (dyl + dyr - 1);
297   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
298   ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
299 
300   /* PetscDraw the axis lines */
301   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xhigh,axis->ylow,ac);CHKERRQ(ierr);
302   ierr = PetscDrawLine(draw,axis->xlow,axis->ylow,axis->xlow,axis->yhigh,ac);CHKERRQ(ierr);
303   ierr = PetscDrawLine(draw,axis->xlow,axis->yhigh,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
304   ierr = PetscDrawLine(draw,axis->xhigh,axis->ylow,axis->xhigh,axis->yhigh,ac);CHKERRQ(ierr);
305 
306   /* PetscDraw the top label */
307   if (axis->toplabel) {
308     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->yhigh + 0.5*th;
309     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->toplabel);CHKERRQ(ierr);
310   }
311 
312   /* PetscDraw the X ticks and labels */
313   if (axis->xticks) {
314     numx = (int)(.15*(axis->xhigh-axis->xlow)/tw); numx = PetscClipInterval(numx,2,6);
315     ierr = (*axis->xticks)(axis->xlow,axis->xhigh,numx,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
316     /* PetscDraw in tick marks */
317     for (i=0; i<ntick; i++) {
318       ierr = PetscDrawLine(draw,tickloc[i],axis->ylow,tickloc[i],axis->ylow+.5*th,tc);CHKERRQ(ierr);
319       ierr = PetscDrawLine(draw,tickloc[i],axis->yhigh,tickloc[i],axis->yhigh-.5*th,tc);CHKERRQ(ierr);
320     }
321     /* label ticks */
322     if (axis->xlabelstr) {
323       for (i=0; i<ntick; i++) {
324         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
325         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
326         else               sep = 0.0;
327         ierr = (*axis->xlabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
328         ierr = PetscDrawStringCentered(draw,tickloc[i],axis->ylow-1.5*th,cc,p);CHKERRQ(ierr);
329       }
330     }
331   }
332   if (axis->xlabel) {
333     PetscReal x = (axis->xlow + axis->xhigh)/2, y = axis->ylow - 1.5*th;
334     if (axis->xlabelstr) y -= 1.5*th;
335     ierr = PetscDrawStringCentered(draw,x,y,cc,axis->xlabel);CHKERRQ(ierr);
336   }
337 
338   /* PetscDraw the Y ticks and labels */
339   if (axis->yticks) {
340     numy = (int)(.50*(axis->yhigh-axis->ylow)/th); numy = PetscClipInterval(numy,2,6);
341     ierr = (*axis->yticks)(axis->ylow,axis->yhigh,numy,&ntick,tickloc,MAXSEGS);CHKERRQ(ierr);
342     /* PetscDraw in tick marks */
343     for (i=0; i<ntick; i++) {
344       ierr = PetscDrawLine(draw,axis->xlow,tickloc[i],axis->xlow+.5*tw,tickloc[i],tc);CHKERRQ(ierr);
345       ierr = PetscDrawLine(draw,axis->xhigh,tickloc[i],axis->xhigh-.5*tw,tickloc[i],tc);CHKERRQ(ierr);
346     }
347     /* label ticks */
348     if (axis->ylabelstr) {
349       for (i=0; i<ntick; i++) {
350         if (i < ntick - 1) sep = tickloc[i+1] - tickloc[i];
351         else if (i > 0)    sep = tickloc[i]   - tickloc[i-1];
352         else               sep = 0.0;
353         ierr = (*axis->ylabelstr)(tickloc[i],sep,&p);CHKERRQ(ierr);
354         ierr = PetscStrlen(p,&len);CHKERRQ(ierr); ytlen = PetscMax(ytlen,len);
355         ierr = PetscDrawString(draw,axis->xlow-(len+.5)*tw,tickloc[i]-.5*th,cc,p);CHKERRQ(ierr);
356       }
357     }
358   }
359   if (axis->ylabel) {
360     PetscReal x = axis->xlow - 2.0*tw, y = (axis->ylow + axis->yhigh)/2;
361     if (axis->ylabelstr) x -= (ytlen+.5)*tw;
362     ierr = PetscStrlen(axis->ylabel,&len);CHKERRQ(ierr);
363     ierr = PetscDrawStringVertical(draw,x,y+len*th/2,cc,axis->ylabel);CHKERRQ(ierr);
364   }
365 
366   ierr = PetscDrawGetCoordinates(draw,&coors[0],&coors[1],&coors[2],&coors[3]);CHKERRQ(ierr);
367 finally:
368   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
369   ierr = MPI_Bcast(coors,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
370   ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
371   PetscFunctionReturn(0);
372 }
373 
374 /*
375     Removes all zeros but one from .0000
376 */
377 PetscErrorCode PetscStripe0(char *buf)
378 {
379   PetscErrorCode ierr;
380   size_t         n;
381   PetscBool      flg;
382   char           *str;
383 
384   PetscFunctionBegin;
385   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
386   ierr = PetscStrendswith(buf,"e00",&flg);CHKERRQ(ierr);
387   if (flg) buf[n-3] = 0;
388   ierr = PetscStrstr(buf,"e0",&str);CHKERRQ(ierr);
389   if (str) {
390     buf[n-2] = buf[n-1];
391     buf[n-1] = 0;
392   }
393   ierr = PetscStrstr(buf,"e-0",&str);CHKERRQ(ierr);
394   if (str) {
395     buf[n-2] = buf[n-1];
396     buf[n-1] = 0;
397   }
398   PetscFunctionReturn(0);
399 }
400 
401 /*
402     Removes all zeros but one from .0000
403 */
404 PetscErrorCode PetscStripAllZeros(char *buf)
405 {
406   PetscErrorCode ierr;
407   size_t         i,n;
408 
409   PetscFunctionBegin;
410   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
411   if (buf[0] != '.') PetscFunctionReturn(0);
412   for (i=1; i<n; i++) {
413     if (buf[i] != '0') PetscFunctionReturn(0);
414   }
415   buf[0] = '0';
416   buf[1] = 0;
417   PetscFunctionReturn(0);
418 }
419 
420 /*
421     Removes trailing zeros
422 */
423 PetscErrorCode PetscStripTrailingZeros(char *buf)
424 {
425   PetscErrorCode ierr;
426   char           *found;
427   size_t         i,n,m = PETSC_MAX_INT;
428 
429   PetscFunctionBegin;
430   /* if there is an e in string DO NOT strip trailing zeros */
431   ierr = PetscStrchr(buf,'e',&found);CHKERRQ(ierr);
432   if (found) PetscFunctionReturn(0);
433 
434   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
435   /* locate decimal point */
436   for (i=0; i<n; i++) {
437     if (buf[i] == '.') {m = i; break;}
438   }
439   /* if not decimal point then no zeros to remove */
440   if (m == PETSC_MAX_INT) PetscFunctionReturn(0);
441   /* start at right end of string removing 0s */
442   for (i=n-1; i>m; i++) {
443     if (buf[i] != '0') PetscFunctionReturn(0);
444     buf[i] = 0;
445   }
446   PetscFunctionReturn(0);
447 }
448 
449 /*
450     Removes leading 0 from 0.22 or -0.22
451 */
452 PetscErrorCode PetscStripInitialZero(char *buf)
453 {
454   PetscErrorCode ierr;
455   size_t         i,n;
456 
457   PetscFunctionBegin;
458   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
459   if (buf[0] == '0') {
460     for (i=0; i<n; i++) buf[i] = buf[i+1];
461   } else if (buf[0] == '-' && buf[1] == '0') {
462     for (i=1; i<n; i++) buf[i] = buf[i+1];
463   }
464   PetscFunctionReturn(0);
465 }
466 
467 /*
468      Removes the extraneous zeros in numbers like 1.10000e6
469 */
470 PetscErrorCode PetscStripZeros(char *buf)
471 {
472   PetscErrorCode ierr;
473   size_t         i,j,n;
474 
475   PetscFunctionBegin;
476   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
477   if (n<5) PetscFunctionReturn(0);
478   for (i=1; i<n-1; i++) {
479     if (buf[i] == 'e' && buf[i-1] == '0') {
480       for (j=i; j<n+1; j++) buf[j-1] = buf[j];
481       ierr = PetscStripZeros(buf);CHKERRQ(ierr);
482       PetscFunctionReturn(0);
483     }
484   }
485   PetscFunctionReturn(0);
486 }
487 
488 /*
489       Removes the plus in something like 1.1e+2 or 1.1e+02
490 */
491 PetscErrorCode PetscStripZerosPlus(char *buf)
492 {
493   PetscErrorCode ierr;
494   size_t         i,j,n;
495 
496   PetscFunctionBegin;
497   ierr = PetscStrlen(buf,&n);CHKERRQ(ierr);
498   if (n<5) PetscFunctionReturn(0);
499   for (i=1; i<n-2; i++) {
500     if (buf[i] == '+') {
501       if (buf[i+1] == '0') {
502         for (j=i+1; j<n; j++) buf[j-1] = buf[j+1];
503         PetscFunctionReturn(0);
504       } else {
505         for (j=i+1; j<n+1; j++) buf[j-1] = buf[j];
506         PetscFunctionReturn(0);
507       }
508     } else if (buf[i] == '-') {
509       if (buf[i+1] == '0') {
510         for (j=i+1; j<n; j++) buf[j] = buf[j+1];
511         PetscFunctionReturn(0);
512       }
513     }
514   }
515   PetscFunctionReturn(0);
516 }
517