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