Date: 2025-03-29T05:58:42+00:00

Actual source code: axisc.c

      1: #include <petsc/private/drawimpl.h>

      3: #define PETSC_DRAW_AXIS_MAX_SEGMENTS 20
      4: PetscClassId PETSC_DRAWAXIS_CLASSID = 0;

      6: /*@
      7:   PetscDrawAxisCreate - Generate the axis data structure.

      9:   Collective

     11:   Input Parameter:
     12: . draw - `PetscDraw` object where axis to be made

     14:   Output Parameter:
     15: . axis - the axis datastructure

     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

     21:   Level: advanced

     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: @*/
     27: PetscErrorCode PetscDrawAxisCreate(PetscDraw draw, PetscDrawAxis *axis)
     28: {
     29:   PetscDrawAxis ad;

     31:   PetscFunctionBegin;
     33:   PetscAssertPointer(axis, 2);

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

     52: /*@
     53:   PetscDrawAxisDestroy - Frees the space used by an axis structure.

     55:   Collective

     57:   Input Parameter:
     58: . axis - the axis context

     60:   Level: advanced

     62: .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`
     63: @*/
     64: PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
     65: {
     66:   PetscFunctionBegin;
     67:   if (!*axis) PetscFunctionReturn(PETSC_SUCCESS);
     69:   if (--((PetscObject)*axis)->refct > 0) {
     70:     *axis = NULL;
     71:     PetscFunctionReturn(PETSC_SUCCESS);
     72:   }

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

     82: /*@
     83:   PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
     84:   tickmarks, and text.

     86:   Logically Collective

     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

     94:   Level: advanced

     96: .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
     97: @*/
     98: PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis, int ac, int tc, int cc)
     99: {
    100:   PetscFunctionBegin;
    105:   axis->ac = ac;
    106:   axis->tc = tc;
    107:   axis->cc = cc;
    108:   PetscFunctionReturn(PETSC_SUCCESS);
    109: }

    111: /*@
    112:   PetscDrawAxisSetLabels -  Sets the x and y axis labels.

    114:   Logically Collective

    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

    122:   Level: advanced

    124:   Notes:
    125:   Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`

    127:   There should be no newlines in the arguments

    129: .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
    130: @*/
    131: PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[])
    132: {
    133:   PetscFunctionBegin;
    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: }

    144: /*@
    145:   PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis

    147:   Logically Collective

    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

    156:   Options Database Key:
    157: . -drawaxis_hold - hold the initial set of axis limits for future plotting

    159:   Level: advanced

    161: .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
    162: @*/
    163: PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax)
    164: {
    165:   PetscFunctionBegin;
    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: }

    176: /*@
    177:   PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis

    179:   Not Collective

    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

    188:   Level: advanced

    190: .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
    191: @*/
    192: PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax)
    193: {
    194:   PetscFunctionBegin;
    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: }

    203: /*@
    204:   PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
    205:   again

    207:   Logically Collective

    209:   Input Parameters:
    210: + axis - the axis
    211: - hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed

    213:   Level: advanced

    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`

    219: .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
    220: @*/
    221: PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold)
    222: {
    223:   PetscFunctionBegin;
    226:   axis->hold = hold;
    227:   PetscFunctionReturn(PETSC_SUCCESS);
    228: }

    230: /*@
    231:   PetscDrawAxisDraw - draws an axis.

    233:   Collective

    235:   Input Parameter:
    236: . axis - `PetscDrawAxis` structure

    238:   Level: advanced

    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).

    246: .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
    247: @*/
    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;

    259:   PetscFunctionBegin;
    261:   PetscCall(PetscDrawIsNull(axis->win, &isnull));
    262:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
    263:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));

    265:   draw = axis->win;

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

    279:   PetscDrawCollectiveBegin(draw);
    280:   if (rank) goto finally;

    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));

    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));

    314:   /* PetscDraw the top label */
    315:   if (axis->toplabel) {
    316:     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;

    318:     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
    319:   }

    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;

    345:     if (axis->xlabelstr) y -= 1.5 * th;
    346:     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
    347:   }

    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;

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

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

    388: /*
    389:     Removes all zeros but one from .0000
    390: */
    391: PetscErrorCode PetscStripe0(char *buf)
    392: {
    393:   size_t    n;
    394:   PetscBool flg;
    395:   char     *str = NULL;

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

    414: /*
    415:     Removes all zeros but one from .0000
    416: */
    417: PetscErrorCode PetscStripAllZeros(char *buf)
    418: {
    419:   size_t i, n;

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

    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
    440: PetscErrorCode PetscStripTrailingZeros(char *buf)
    441: {
    442:   char  *found = NULL;
    443:   size_t i, n, m = MAX_SIZE_T;

    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);

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

    468: /*
    469:     Removes leading 0 from 0.22 or -0.22
    470: */
    471: PetscErrorCode PetscStripInitialZero(char *buf)
    472: {
    473:   size_t i, n;

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

    485: /*
    486:      Removes the extraneous zeros in numbers like 1.10000e6
    487: */
    488: PetscErrorCode PetscStripZeros(char *buf)
    489: {
    490:   size_t i, j, n;

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

    505: /*
    506:       Removes the plus in something like 1.1e+2 or 1.1e+02
    507: */
    508: PetscErrorCode PetscStripZerosPlus(char *buf)
    509: {
    510:   size_t i, j, n;

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