#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*#include "gr.h"*/
#include "gridit.h"

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

#define Integer static int
#define Real static double

static int idcldp(int *ndp, double *xd, double *yd, int *ncp, int *ipc)
{
  Integer j1, j2, j3, j4;
  Real x1, y1, r1, r2;
  Integer ip1, ip2, ip3;
  Real dx12, dy12, dx13, dy13;
  Integer jmx, ipc0[25], ncp0, ndp0;
  Real dsq0[25], dsqi;
  Integer ip2mn, ip3mn, nclpt;
  Real dsqmn, dsqmx;

  /* THIS SUBROUTINE SELECTS SEVERAL DATA POINTS THAT ARE CLOSEST */
  /* TO EACH OF THE DATA POINT. */
  /* THE INPUT PARAMETERS ARE */
  /*     NDP = NUMBER OF DATA POINTS, */
  /*     XD,YD = ARRAYS OF DIMENSION NDP CONTAINING THE X AND Y */
  /*           COORDINATES OF THE DATA POINTS, */
  /*     NCP = NUMBER OF DATA POINTS CLOSEST TO EACH DATA */
  /*           POINTS. */
  /* THE OUTPUT PARAMETER IS */
  /*     IPC = INTEGER ARRAY OF DIMENSION NCP*NDP, WHERE THE */
  /*           POINT NUMBERS OF NCP DATA POINTS CLOSEST TO */
  /*           EACH OF THE NDP DATA POINTS ARE TO BE STORED. */
  /* THIS SUBROUTINE ARBITRARILY SETS A RESTRICTION THAT NCP MUST */
  /* NOT EXCEED 25. */

  /* PRELIMINARY PROCESSING */
  ip3mn = 0;
  jmx = 0;
  ndp0 = *ndp;
  ncp0 = *ncp;
  dsqmn = 0.;
  if (ndp0 >= 2)
    {
      if (ncp0 >= 1 && ncp0 <= 25 && ncp0 < ndp0)
        {
          /* CALCULATION */
          for (ip1 = 1; ip1 <= ndp0; ++ip1)
            {
              /* - SELECTS NCP POINTS. */
              x1 = xd[ip1 - 1];
              y1 = yd[ip1 - 1];
              j1 = 0;
              dsqmx = 0.;
              for (ip2 = 1; ip2 <= ndp0; ++ip2)
                {
                  if (ip2 != ip1)
                    {
                      r1 = xd[ip2 - 1] - x1;
                      r2 = yd[ip2 - 1] - y1;
                      dsqi = r1 * r1 + r2 * r2;
                      ++j1;
                      dsq0[j1 - 1] = dsqi;
                      ipc0[j1 - 1] = ip2;
                      if (dsqi > dsqmx)
                        {
                          dsqmx = dsqi;
                          jmx = j1;
                        }
                      if (j1 >= ncp0)
                        {
                          goto L30;
                        }
                    }
                  /* L20: */
                }
            L30:
              ip2mn = ip2 + 1;
              if (ip2mn <= ndp0)
                {
                  for (ip2 = ip2mn; ip2 <= ndp0; ++ip2)
                    {
                      if (ip2 != ip1)
                        {
                          r1 = xd[ip2 - 1] - x1;
                          r2 = yd[ip2 - 1] - y1;
                          dsqi = r1 * r1 + r2 * r2;
                          if (dsqi < dsqmx)
                            {
                              dsq0[jmx - 1] = dsqi;
                              ipc0[jmx - 1] = ip2;
                              dsqmx = 0.;
                              for (j1 = 1; j1 <= ncp0; ++j1)
                                {
                                  if (dsq0[j1 - 1] > dsqmx)
                                    {
                                      dsqmx = dsq0[j1 - 1];
                                      jmx = j1;
                                    }
                                  /* L50: */
                                }
                            }
                        }
                      /* L40: */
                    }
                }
              /* - CHECKS IF ALL THE NCP+1 POINTS ARE COLLINEAR. */
              ip2 = ipc0[0];
              dx12 = xd[ip2 - 1] - x1;
              dy12 = yd[ip2 - 1] - y1;
              for (j3 = 2; j3 <= ncp0; ++j3)
                {
                  ip3 = ipc0[j3 - 1];
                  dx13 = xd[ip3 - 1] - x1;
                  dy13 = yd[ip3 - 1] - y1;
                  if ((r1 = dy13 * dx12 - dx13 * dy12, fabs(r1)) > 1e-12)
                    {
                      goto L70;
                    }
                  /* L60: */
                }
              /* - SEARCHES FOR THE CLOSEST NONCOLLINEAR POINT. */
              nclpt = 0;
              for (ip3 = 1; ip3 <= ndp0; ++ip3)
                {
                  if (ip3 != ip1)
                    {
                      for (j4 = 1; j4 <= ncp0; ++j4)
                        {
                          if (ip3 == ipc0[j4 - 1])
                            {
                              goto L80;
                            }
                          /* L90: */
                        }
                      dx13 = xd[ip3 - 1] - x1;
                      dy13 = yd[ip3 - 1] - y1;
                      if ((r1 = dy13 * dx12 - dx13 * dy12, fabs(r1)) > 1e-12)
                        {
                          r1 = xd[ip3 - 1] - x1;
                          r2 = yd[ip3 - 1] - y1;
                          dsqi = r1 * r1 + r2 * r2;
                          if (nclpt != 0)
                            {
                              if (dsqi >= dsqmn)
                                {
                                  goto L80;
                                }
                            }
                          nclpt = 1;
                          dsqmn = dsqi;
                          ip3mn = ip3;
                        }
                    }
                L80:;
                }
              if (nclpt == 0)
                {
                  goto L100;
                }
              else
                {
                  dsqmx = dsqmn;
                  ipc0[jmx - 1] = ip3mn;
                }
              /* - REPLACES THE LOCAL ARRAY FOR THE OUTPUT ARRAY. */
            L70:
              j1 = (ip1 - 1) * ncp0;
              for (j2 = 1; j2 <= ncp0; ++j2)
                {
                  ++j1;
                  ipc[j1 - 1] = ipc0[j2 - 1];
                  /* L110: */
                }
              /* L10: */
            }
          return 0;
        L100:
          fprintf(stderr, " ***   ALL COLLINEAR DATA POINTS.\n");
          goto L120;
        }
    }
  /* ERROR EXIT */
  fprintf(stderr, " ***   IMPROPER INPUT PARAMETER VALUE(S).\n");
L120:
  fprintf(stderr,
          "   NDP =%5d   NCP =%5d\n"
          " ERROR DETECTED IN ROUTINE   IDCLDP\n",
          ndp0, ncp0);
  ipc[0] = 0; /*1*/
  return 0;
}

static int idgrid(double *xd, double *yd, int *nt, int *ipt, int *nl, int *ipl, int *nxi, int *nyi, double *xi,
                  double *yi, int *ngp, int *igp)
{
  Integer l;
  Real x1, y1, x2, y2, x3, y3, r1, r2;
  Integer il0, nl0, ip1, ip2, it0, ip3, nt0, ixi, iyi;
  Real yii, xii;
  Integer izi;
  Real xmn, ymn, xmx, ymx;
  Integer ngp0, ngp1, ilp1, nxi0, nyi0, il0t3, insd, it0t3;
  Real ximn, yimn, expr, ximx, yimx;
  Integer jigp0, jigp1, jngp0, jngp1, ilp1t3, iximn, iximx, jigp1i, nxinyi;

  /* THIS SUBROUTINE ORGANIZES GRID POINTS FOR SURFACE FITTING BY */
  /* SORTING THEM IN ASCENDING ORDER OF TRIANGLE NUMBERS AND OF THE */
  /* BORDER LINE SEGMENT NUMBER. */
  /* THE INPUT PARAMETERS ARE */
  /*     XD,YD = ARRAYS OF DIMENSION NDP CONTAINING THE X AND Y */
  /*           COORDINATES OF THE DATA POINTS, WHERE NDP IS THE */
  /*           NUMBER OF THE DATA POINTS, */
  /*     NT  = NUMBER OF TRIANGLES, */
  /*     IPT = INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE */
  /*           POINT NUMBERS OF THE VERTEXES OF THE TRIANGLES, */
  /*     NL  = NUMBER OF BORDER LINE SEGMENTS, */
  /*     IPL = INTEGER ARRAY OF DIMENSION 3*NL CONTAINING THE */
  /*           POINT NUMBERS OF THE END POINTS OF THE BORDER */
  /*           LINE SEGMENTS AND THEIR RESPECTIVE TRIANGLE */
  /*           NUMBERS, */
  /*     NXI = NUMBER OF GRID POINTS IN THE X COORDINATE, */
  /*     NYI = NUMBER OF GRID POINTS IN THE Y COORDINATE, */
  /*     XI,YI = ARRAYS OF DIMENSION NXI AND NYI CONTAINING */
  /*           THE X AND Y COORDINATES OF THE GRID POINTS, */
  /*           RESPECTIVELY. */
  /* THE OUTPUT PARAMETERS ARE */
  /*     NGP = INTEGER ARRAY OF DIMENSION 2*(NT+2*NL) WHERE THE */
  /*           NUMBER OF GRID POINTS THAT BELONG TO EACH OF THE */
  /*           TRIANGLES OR OF THE BORDER LINE SEGMENTS ARE TO */
  /*           BE STORED, */
  /*     IGP = INTEGER ARRAY OF DIMENSION NXI*NYI WHERE THE */
  /*           GRID POINT NUMBERS ARE TO BE STORED IN ASCENDING */
  /*           ORDER OF THE TRIANGLE NUMBER AND THE BORDER LINE */
  /*           SEGMENT NUMBER. */

  nt0 = *nt;
  nl0 = *nl;
  nxi0 = iximn = *nxi;
  nyi0 = *nyi;
  nxinyi = nxi0 * nyi0;
  r1 = xi[0], r2 = xi[nxi0 - 1];
  ximn = min(r1, r2);
  r1 = xi[0], r2 = xi[nxi0 - 1];
  ximx = max(r1, r2);
  r1 = yi[0], r2 = yi[nyi0 - 1];
  yimn = min(r1, r2);
  r1 = yi[0], r2 = yi[nyi0 - 1];
  yimx = max(r1, r2);
  /* DETERMINES GRID POINTS INSIDE THE DATA AREA. */
  jngp0 = 0;
  jngp1 = 2 * (nt0 + 2 * nl0) + 1;
  jigp0 = 0;
  jigp1 = nxinyi + 1;
  for (it0 = 1; it0 <= nt0; ++it0)
    {
      ngp0 = 0;
      ngp1 = 0;
      it0t3 = it0 * 3;
      ip1 = ipt[it0t3 - 3];
      ip2 = ipt[it0t3 - 2];
      ip3 = ipt[it0t3 - 1];
      x1 = xd[ip1 - 1];
      y1 = yd[ip1 - 1];
      x2 = xd[ip2 - 1];
      y2 = yd[ip2 - 1];
      x3 = xd[ip3 - 1];
      y3 = yd[ip3 - 1];
      r1 = min(x1, x2);
      xmn = min(r1, x3);
      r1 = max(x1, x2);
      xmx = max(r1, x3);
      r1 = min(y1, y2);
      ymn = min(r1, y3);
      r1 = max(y1, y2);
      ymx = max(r1, y3);
      insd = 0;
      for (ixi = 1; ixi <= nxi0; ++ixi)
        {
          if (xi[ixi - 1] >= xmn && xi[ixi - 1] <= xmx)
            {
              if (insd != 1)
                {
                  insd = 1;
                  iximn = ixi;
                }
            }
          else if (insd != 0)
            {
              goto L30;
            }
          /* L20: */
        }
      if (insd == 0)
        {
          goto L40;
        }
      else
        {
          iximx = nxi0;
          goto L50;
        }
    L30:
      iximx = ixi - 1;
    L50:
      for (iyi = 1; iyi <= nyi0; ++iyi)
        {
          yii = yi[iyi - 1];
          if (yii >= ymn && yii <= ymx)
            {
              for (ixi = iximn; ixi <= iximx; ++ixi)
                {
                  xii = xi[ixi - 1];
                  l = 0;
                  expr = (x1 - xii) * (y2 - yii) - (y1 - yii) * (x2 - xii);
                  if (expr < 0.)
                    {
                      goto L70;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  expr = (x2 - xii) * (y3 - yii) - (y2 - yii) * (x3 - xii);
                  if (expr < 0.)
                    {
                      goto L70;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  expr = (x3 - xii) * (y1 - yii) - (y3 - yii) * (x1 - xii);
                  if (expr < 0.)
                    {
                      goto L70;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  izi = nxi0 * (iyi - 1) + ixi;
                  if (l == 1)
                    {
                      if (jigp1 <= nxinyi)
                        {
                          for (jigp1i = jigp1; jigp1i <= nxinyi; ++jigp1i)
                            {
                              if (izi == igp[jigp1i - 1])
                                {
                                  goto L70;
                                }
                              /* L140: */
                            }
                        }
                      ++ngp1;
                      --jigp1;
                      igp[jigp1 - 1] = izi;
                    }
                  else
                    {
                      ++ngp0;
                      ++jigp0;
                      igp[jigp0 - 1] = izi;
                    }
                L70:;
                }
            }
          /* L60: */
        }
    L40:
      ++jngp0;
      ngp[jngp0 - 1] = ngp0;
      --jngp1;
      ngp[jngp1 - 1] = ngp1;
      /* L10: */
    }
  /* DETERMINES GRID POINTS OUTSIDE THE DATA AREA. */
  /* - IN SEMI-INFINITE RECTANGULAR AREA. */
  for (il0 = 1; il0 <= nl0; ++il0)
    {
      ngp0 = 0;
      ngp1 = 0;
      il0t3 = il0 * 3;
      ip1 = ipl[il0t3 - 3];
      ip2 = ipl[il0t3 - 2];
      x1 = xd[ip1 - 1];
      y1 = yd[ip1 - 1];
      x2 = xd[ip2 - 1];
      y2 = yd[ip2 - 1];
      xmn = ximn;
      xmx = ximx;
      ymn = yimn;
      ymx = yimx;
      if (y2 >= y1)
        {
          xmn = min(x1, x2);
        }
      if (y2 <= y1)
        {
          xmx = max(x1, x2);
        }
      if (x2 <= x1)
        {
          ymn = min(y1, y2);
        }
      if (x2 >= x1)
        {
          ymx = max(y1, y2);
        }
      insd = 0;
      for (ixi = 1; ixi <= nxi0; ++ixi)
        {
          if (xi[ixi - 1] >= xmn && xi[ixi - 1] <= xmx)
            {
              if (insd != 1)
                {
                  insd = 1;
                  iximn = ixi;
                }
            }
          else if (insd != 0)
            {
              goto L170;
            }
          /* L160: */
        }
      if (insd == 0)
        {
          goto L180;
        }
      else
        {
          iximx = nxi0;
          goto L190;
        }
    L170:
      iximx = ixi - 1;
    L190:
      for (iyi = 1; iyi <= nyi0; ++iyi)
        {
          yii = yi[iyi - 1];
          if (yii >= ymn && yii <= ymx)
            {
              for (ixi = iximn; ixi <= iximx; ++ixi)
                {
                  xii = xi[ixi - 1];
                  l = 0;
                  expr = (x1 - xii) * (y2 - yii) - (y1 - yii) * (x2 - xii);
                  if (expr > 0.)
                    {
                      goto L210;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  expr = (x2 - x1) * (xii - x1) + (y2 - y1) * (yii - y1);
                  if (expr < 0.)
                    {
                      goto L210;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  expr = (x1 - x2) * (xii - x2) + (y1 - y2) * (yii - y2);
                  if (expr < 0.)
                    {
                      goto L210;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  izi = nxi0 * (iyi - 1) + ixi;
                  if (l == 1)
                    {
                      if (jigp1 <= nxinyi)
                        {
                          for (jigp1i = jigp1; jigp1i <= nxinyi; ++jigp1i)
                            {
                              if (izi == igp[jigp1i - 1])
                                {
                                  goto L210;
                                }
                              /* L280: */
                            }
                        }
                      ++ngp1;
                      --jigp1;
                      igp[jigp1 - 1] = izi;
                    }
                  else
                    {
                      ++ngp0;
                      ++jigp0;
                      igp[jigp0 - 1] = izi;
                    }
                L210:;
                }
            }
          /* L200: */
        }
    L180:
      ++jngp0;
      ngp[jngp0 - 1] = ngp0;
      --jngp1;
      ngp[jngp1 - 1] = ngp1;
      /* - IN SEMI-INFINITE TRIANGULAR AREA. */
      ngp0 = 0;
      ngp1 = 0;
      ilp1 = il0 % nl0 + 1;
      ilp1t3 = ilp1 * 3;
      ip3 = ipl[ilp1t3 - 2];
      x3 = xd[ip3 - 1];
      y3 = yd[ip3 - 1];
      xmn = ximn;
      xmx = ximx;
      ymn = yimn;
      ymx = yimx;
      if (y3 >= y2 && y2 >= y1)
        {
          xmn = x2;
        }
      if (y3 <= y2 && y2 <= y1)
        {
          xmx = x2;
        }
      if (x3 <= x2 && x2 <= x1)
        {
          ymn = y2;
        }
      if (x3 >= x2 && x2 >= x1)
        {
          ymx = y2;
        }
      insd = 0;
      for (ixi = 1; ixi <= nxi0; ++ixi)
        {
          if (xi[ixi - 1] >= xmn && xi[ixi - 1] <= xmx)
            {
              if (insd != 1)
                {
                  insd = 1;
                  iximn = ixi;
                }
            }
          else if (insd != 0)
            {
              goto L300;
            }
          /* L290: */
        }
      if (insd == 0)
        {
          goto L310;
        }
      else
        {
          iximx = nxi0;
          goto L320;
        }
    L300:
      iximx = ixi - 1;
    L320:
      for (iyi = 1; iyi <= nyi0; ++iyi)
        {
          yii = yi[iyi - 1];
          if (yii >= ymn && yii <= ymx)
            {
              for (ixi = iximn; ixi <= iximx; ++ixi)
                {
                  xii = xi[ixi - 1];
                  l = 0;
                  expr = (x1 - x2) * (xii - x2) + (y1 - y2) * (yii - y2);
                  if (expr > 0.)
                    {
                      goto L340;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  expr = (x3 - x2) * (xii - x2) + (y3 - y2) * (yii - y2);
                  if (expr > 0.)
                    {
                      goto L340;
                    }
                  if (expr == 0.)
                    {
                      l = 1;
                    }
                  izi = nxi0 * (iyi - 1) + ixi;
                  if (l == 1)
                    {
                      if (jigp1 <= nxinyi)
                        {
                          for (jigp1i = jigp1; jigp1i <= nxinyi; ++jigp1i)
                            {
                              if (izi == igp[jigp1i - 1])
                                {
                                  goto L340;
                                }
                              /* L390: */
                            }
                        }
                      ++ngp1;
                      --jigp1;
                      igp[jigp1 - 1] = izi;
                    }
                  else
                    {
                      ++ngp0;
                      ++jigp0;
                      igp[jigp0 - 1] = izi;
                    }
                L340:;
                }
            }
          /* L330: */
        }
    L310:
      ++jngp0;
      ngp[jngp0 - 1] = ngp0;
      --jngp1;
      ngp[jngp1 - 1] = ngp1;
      /* L150: */
    }
  return 0;
}

static int idpdrv(int *ndp, double *xd, double *yd, double *zd, int *ncp, int *ipc, double *pd)
{
  Real x0, y0, z0;
  Integer ic1, ic2, ip0;
  Real dx1, dy1, dz1, dx2, dy2, dz2, zx0, zy0;
  Integer jpd, ipi;
  Real nmx, nmy, nmz;
  Integer jpd0, ncp0, ndp0;
  Real dzx1, dzy1, dzx2, dzy2;
  Integer jipc;
  Real dnmx, dnmy, dnmz, nmxx, nmxy, nmyx, nmyy;
  Integer jipc0, ic2mn, ncpm1;
  Real dnmxx, dnmxy, dnmyx, dnmyy;

  /* THIS SUBROUTINE ESTIMATES PARTIAL DERIVATIVES OF THE FIRST AND */
  /* SECOND ORDER AT THE DATA POINTS. */
  /* THE INPUT PARAMETERS ARE */
  /*     NDP = NUMBER OF DATA POINTS, */
  /*     XD,YD,ZD = ARRAYS OF DIMENSION NDP CONTAINING THE X, */
  /*           Y, AND Z COORDINATES OF THE DATA POINTS, */
  /*     NCP = NUMBER OF ADDITIONAL DATA POINTS USED FOR ESTI- */
  /*           MATING PARTIAL DERIVATIVES AT EACH DATA POINT, */
  /*     IPC = INTEGER ARRAY OF DIMENSION NCP*NDP CONTAINING */
  /*           THE POINT NUMBERS OF NCP DATA POINTS CLOSEST TO */
  /*           EACH OF THE NDP DATA POINTS. */
  /* THE OUTPUT PARAMETER IS */
  /*     PD  = ARRAY OF DIMENSION 5*NDP, WHERE THE ESTIMATED */
  /*           ZX, ZY, ZXX, ZXY, AND ZYY VALUES AT THE DATA */
  /*           POINTS ARE TO BE STORED. */

  ndp0 = *ndp;
  ncp0 = *ncp;
  ncpm1 = ncp0 - 1;
  /* ESTIMATION OF ZX AND ZY */
  for (ip0 = 1; ip0 <= ndp0; ++ip0)
    {
      x0 = xd[ip0 - 1];
      y0 = yd[ip0 - 1];
      z0 = zd[ip0 - 1];
      nmx = 0.;
      nmy = 0.;
      nmz = 0.;
      jipc0 = ncp0 * (ip0 - 1);
      for (ic1 = 1; ic1 <= ncpm1; ++ic1)
        {
          jipc = jipc0 + ic1;
          ipi = ipc[jipc - 1];
          dx1 = xd[ipi - 1] - x0;
          dy1 = yd[ipi - 1] - y0;
          dz1 = zd[ipi - 1] - z0;
          ic2mn = ic1 + 1;
          for (ic2 = ic2mn; ic2 <= ncp0; ++ic2)
            {
              jipc = jipc0 + ic2;
              ipi = ipc[jipc - 1];
              dx2 = xd[ipi - 1] - x0;
              dy2 = yd[ipi - 1] - y0;
              dnmz = dx1 * dy2 - dy1 * dx2;
              if (fabs(dnmz) > 1e-12)
                {
                  dz2 = zd[ipi - 1] - z0;
                  dnmx = dy1 * dz2 - dz1 * dy2;
                  dnmy = dz1 * dx2 - dx1 * dz2;
                  if (dnmz < 0.)
                    {
                      dnmx = -dnmx;
                      dnmy = -dnmy;
                      dnmz = -dnmz;
                    }
                  nmx += dnmx;
                  nmy += dnmy;
                  nmz += dnmz;
                }
              /* L30: */
            }
          /* L20: */
        }
      jpd0 = ip0 * 5;
      pd[jpd0 - 5] = -nmx / nmz;
      pd[jpd0 - 4] = -nmy / nmz;
      /* L10: */
    }
  /* ESTIMATION OF ZXX, ZXY, AND ZYY */
  for (ip0 = 1; ip0 <= ndp0; ++ip0)
    {
      jpd0 += 5;
      x0 = xd[ip0 - 1];
      jpd0 = ip0 * 5;
      y0 = yd[ip0 - 1];
      zx0 = pd[jpd0 - 5];
      zy0 = pd[jpd0 - 4];
      nmxx = 0.;
      nmxy = 0.;
      nmyx = 0.;
      nmyy = 0.;
      nmz = 0.;
      jipc0 = ncp0 * (ip0 - 1);
      for (ic1 = 1; ic1 <= ncpm1; ++ic1)
        {
          jipc = jipc0 + ic1;
          ipi = ipc[jipc - 1];
          dx1 = xd[ipi - 1] - x0;
          dy1 = yd[ipi - 1] - y0;
          jpd = ipi * 5;
          dzx1 = pd[jpd - 5] - zx0;
          dzy1 = pd[jpd - 4] - zy0;
          ic2mn = ic1 + 1;
          for (ic2 = ic2mn; ic2 <= ncp0; ++ic2)
            {
              jipc = jipc0 + ic2;
              ipi = ipc[jipc - 1];
              dx2 = xd[ipi - 1] - x0;
              dy2 = yd[ipi - 1] - y0;
              dnmz = dx1 * dy2 - dy1 * dx2;
              if (fabs(dnmz) > 1e-12)
                {
                  jpd = ipi * 5;
                  dzx2 = pd[jpd - 5] - zx0;
                  dzy2 = pd[jpd - 4] - zy0;
                  dnmxx = dy1 * dzx2 - dzx1 * dy2;
                  dnmxy = dzx1 * dx2 - dx1 * dzx2;
                  dnmyx = dy1 * dzy2 - dzy1 * dy2;
                  dnmyy = dzy1 * dx2 - dx1 * dzy2;
                  if (dnmz < 0.)
                    {
                      dnmxx = -dnmxx;
                      dnmxy = -dnmxy;
                      dnmyx = -dnmyx;
                      dnmyy = -dnmyy;
                      dnmz = -dnmz;
                    }
                  nmxx += dnmxx;
                  nmxy += dnmxy;
                  nmyx += dnmyx;
                  nmyy += dnmyy;
                  nmz += dnmz;
                }
              /* L60: */
            }
          /* L50: */
        }
      pd[jpd0 - 3] = -nmxx / nmz;
      pd[jpd0 - 2] = -(nmxy + nmyx) / (nmz * 2.);
      pd[jpd0 - 1] = -nmyy / nmz;
      /* L40: */
    }
  return 0;
}

static int idptip(double *xd, double *yd, double *zd, int *nt, int *ipt, int *nl, int *ipl, double *pdd, int *iti,
                  double *xii, double *yii, double *zii, int *itpv)
{
  Real ap = 0., bp = 0., cp = 0., dp = 0., x0 = 0., y0 = 0.;
  Real p5 = 0., p00 = 0., p01 = 0., p02 = 0., p03 = 0., p04 = 0.;
  Real p05 = 0., p10 = 0., p11 = 0., p12 = 0., p13 = 0., p14 = 0.;
  Real p20 = 0., p21 = 0., p22 = 0., p23 = 0., p30 = 0., p31 = 0.;
  Real p32 = 0., p40 = 0., p41 = 0., p50 = 0.;
  Real a, b, c, d;
  Integer i;
  Real u, v, x[3], y[3], z[3], g1, h1, h2, h3, g2, p0, p1, p2, p3, p4;
  Real aa, ab, bb, ad, bc, cc, cd, dd, ac;
  Real pd[15], lu, lv;
  Real zu[3], zv[3], dx, dy;
  Integer il1, il2, it0, idp, jpd, kpd;
  Real dlt;
  Integer ntl;
  Real zuu[3], zuv[3], zvv[3], act2, bdt2, adbc;
  Integer jpdd, jipl, jipt;
  Real csuv, thus, thsv, thuv, thxu;

  /* THIS SUBROUTINE PERFORMS PUNCTUAL INTERPOLATION OR EXTRAPOLA- */
  /* TION, I.E., DETERMINES THE Z VALUE AT A POINT. */
  /* THE INPUT PARAMETERS ARE */
  /*     XD,YD,ZD = ARRAYS OF DIMENSION NDP CONTAINING THE X, */
  /*           Y, AND Z COORDINATES OF THE DATA POINTS, WHERE */
  /*           NDP IS THE NUMBER OF THE DATA POINTS, */
  /*     NT  = NUMBER OF TRIANGLES, */
  /*     IPT = INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE */
  /*           POINT NUMBERS OF THE VERTEXES OF THE TRIANGLES, */
  /*     NL  = NUMBER OF BORDER LINE SEGMENTS, */
  /*     IPL = INTEGER ARRAY OF DIMENSION 3*NL CONTAINING THE */
  /*           POINT NUMBERS OF THE END POINTS OF THE BORDER */
  /*           LINE SEGMENTS AND THEIR RESPECTIVE TRIANGLE */
  /*           NUMBERS, */
  /*     PDD = ARRAY OF DIMENSION 5*NDP CONTAINING THE PARTIAL */
  /*           DERIVATIVES AT THE DATA POINTS, */
  /*     ITI = TRIANGLE NUMBER OF THE TRIANGLE IN WHICH LIES */
  /*           THE POINT FOR WHICH INTERPOLATION IS TO BE */
  /*           PERFORMED, */
  /*     XII,YII = X AND Y COORDINATES OF THE POINT FOR WHICH */
  /*           INTERPOLATION IS TO BE PERFORMED. */
  /* THE OUTPUT PARAMETER IS */
  /*     ZII = INTERPOLATED Z VALUE. */

  it0 = *iti;
  ntl = *nt + *nl;
  if (it0 <= ntl)
    {
      /* CALCULATION OF ZII BY INTERPOLATION. */
      /* CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. */
      if (it0 != *itpv)
        {
          /* LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE */
          /* VERTEXES. */
          jipt = (it0 - 1) * 3;
          jpd = 0;
          for (i = 1; i <= 3; ++i)
            {
              ++jipt;
              idp = ipt[jipt - 1];
              x[i - 1] = xd[idp - 1];
              y[i - 1] = yd[idp - 1];
              z[i - 1] = zd[idp - 1];
              jpdd = (idp - 1) * 5;
              for (kpd = 1; kpd <= 5; ++kpd)
                {
                  ++jpd;
                  ++jpdd;
                  pd[jpd - 1] = pdd[jpdd - 1];
                  /* L20: */
                }
              /* L10: */
            }
          /* DETERMINES THE COEFFICIENTS FOR THE COORDINATE SYSTEM */
          /* TRANSFORMATION FROM THE X-Y SYSTEM TO THE U-V SYSTEM */
          /* AND VICE VERSA. */
          x0 = x[0];
          y0 = y[0];
          a = x[1] - x0;
          b = x[2] - x0;
          c = y[1] - y0;
          d = y[2] - y0;
          ad = a * d;
          bc = b * c;
          dlt = ad - bc;
          ap = d / dlt;
          bp = -b / dlt;
          cp = -c / dlt;
          dp = a / dlt;
          /* CONVERTS THE PARTIAL DERIVATIVES AT THE VERTEXES OF THE */
          /* TRIANGLE FOR THE U-V COORDINATE SYSTEM. */
          aa = a * a;
          act2 = a * 2. * c;
          cc = c * c;
          ab = a * b;
          adbc = ad + bc;
          cd = c * d;
          bb = b * b;
          bdt2 = b * 2. * d;
          dd = d * d;
          for (i = 1; i <= 3; ++i)
            {
              jpd = i * 5;
              zu[i - 1] = a * pd[jpd - 5] + c * pd[jpd - 4];
              zv[i - 1] = b * pd[jpd - 5] + d * pd[jpd - 4];
              zuu[i - 1] = aa * pd[jpd - 3] + act2 * pd[jpd - 2] + cc * pd[jpd - 1];
              zuv[i - 1] = ab * pd[jpd - 3] + adbc * pd[jpd - 2] + cd * pd[jpd - 1];
              zvv[i - 1] = bb * pd[jpd - 3] + bdt2 * pd[jpd - 2] + dd * pd[jpd - 1];
              /* L30: */
            }
          /* CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. */
          p00 = z[0];
          p10 = zu[0];
          p01 = zv[0];
          p20 = zuu[0] * .5;
          p11 = zuv[0];
          p02 = zvv[0] * .5;
          h1 = z[1] - p00 - p10 - p20;
          h2 = zu[1] - p10 - zuu[0];
          h3 = zuu[1] - zuu[0];
          p30 = h1 * 10. - h2 * 4. + h3 * .5;
          p40 = h1 * -15. + h2 * 7. - h3;
          p50 = h1 * 6. - h2 * 3. + h3 * .5;
          p5 = p50;
          h1 = z[2] - p00 - p01 - p02;
          h2 = zv[2] - p01 - zvv[0];
          h3 = zvv[2] - zvv[0];
          p03 = h1 * 10. - h2 * 4. + h3 * .5;
          p04 = h1 * -15. + h2 * 7. - h3;
          p05 = h1 * 6. - h2 * 3. + h3 * .5;
          lu = sqrt(aa + cc);
          lv = sqrt(bb + dd);
          thxu = atan2(c, a);
          thuv = atan2(d, b) - thxu;
          csuv = cos(thuv);
          p41 = lv * 5. * csuv / lu * p50;
          p14 = lu * 5. * csuv / lv * p05;
          h1 = zv[1] - p01 - p11 - p41;
          h2 = zuv[1] - p11 - p41 * 4.;
          p21 = h1 * 3. - h2;
          p31 = h1 * -2. + h2;
          h1 = zu[2] - p10 - p11 - p14;
          h2 = zuv[2] - p11 - p14 * 4.;
          p12 = h1 * 3. - h2;
          p13 = h1 * -2. + h2;
          thus = atan2(d - c, b - a) - thxu;
          thsv = thuv - thus;
          aa = sin(thsv) / lu;
          bb = -cos(thsv) / lu;
          cc = sin(thus) / lv;
          dd = cos(thus) / lv;
          ac = aa * cc;
          ad = aa * dd;
          bc = bb * cc;
          g1 = aa * ac * (bc * 3. + ad * 2.);
          g2 = cc * ac * (ad * 3. + bc * 2.);
          h1 = -aa * aa * aa * (aa * 5. * bb * p50 + (bc * 4. + ad) * p41) -
               cc * cc * cc * (cc * 5. * dd * p05 + (ad * 4. + bc) * p14);
          h2 = zvv[1] * .5 - p02 - p12;
          h3 = zuu[2] * .5 - p20 - p21;
          p22 = (g1 * h2 + g2 * h3 - h1) / (g1 + g2);
          p32 = h2 - p22;
          p23 = h3 - p22;
          *itpv = it0;
        }
      /* CONVERTS XII AND YII TO U-V SYSTEM. */
      dx = *xii - x0;
      dy = *yii - y0;
      u = ap * dx + bp * dy;
      v = cp * dx + dp * dy;
      /* EVALUATES THE POLYNOMIAL. */
      p0 = p00 + v * (p01 + v * (p02 + v * (p03 + v * (p04 + v * p05))));
      p1 = p10 + v * (p11 + v * (p12 + v * (p13 + v * p14)));
      p2 = p20 + v * (p21 + v * (p22 + v * p23));
      p3 = p30 + v * (p31 + v * p32);
      p4 = p40 + v * p41;
      *zii = p0 + u * (p1 + u * (p2 + u * (p3 + u * (p4 + u * p5))));
    }
  else
    {
      il1 = it0 / ntl;
      il2 = it0 - il1 * ntl;
      if (il1 == il2)
        {
          /* CALCULATION OF ZII BY EXTRAPOLATION IN THE RECTANGLE. */
          /* CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. */
          if (it0 != *itpv)
            {
              /* LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE END */
              /* POINTS OF THE BORDER LINE SEGMENT. */
              jipl = (il1 - 1) * 3;
              jpd = 0;
              for (i = 1; i <= 2; ++i)
                {
                  ++jipl;
                  idp = ipl[jipl - 1];
                  x[i - 1] = xd[idp - 1];
                  y[i - 1] = yd[idp - 1];
                  z[i - 1] = zd[idp - 1];
                  jpdd = (idp - 1) * 5;
                  for (kpd = 1; kpd <= 5; ++kpd)
                    {
                      ++jpd;
                      ++jpdd;
                      pd[jpd - 1] = pdd[jpdd - 1];
                      /* L50: */
                    }
                  /* L40: */
                }
              /* DETERMINES THE COEFFICIENTS FOR THE COORDINATE SYSTEM */
              /* TRANSFORMATION FROM THE X-Y SYSTEM TO THE U-V SYSTEM */
              /* AND VICE VERSA. */
              x0 = x[0];
              y0 = y[0];
              a = y[1] - y[0];
              b = x[1] - x[0];
              c = -b;
              d = a;
              ad = a * d;
              bc = b * c;
              dlt = ad - bc;
              ap = d / dlt;
              bp = -b / dlt;
              cp = -bp;
              dp = ap;
              /* CONVERTS THE PARTIAL DERIVATIVES AT THE END POINTS OF THE */
              /* BORDER LINE SEGMENT FOR THE U-V COORDINATE SYSTEM. */
              aa = a * a;
              act2 = a * 2. * c;
              cc = c * c;
              ab = a * b;
              adbc = ad + bc;
              cd = c * d;
              bb = b * b;
              bdt2 = b * 2. * d;
              dd = d * d;
              for (i = 1; i <= 2; ++i)
                {
                  jpd = i * 5;
                  zu[i - 1] = a * pd[jpd - 5] + c * pd[jpd - 4];
                  zv[i - 1] = b * pd[jpd - 5] + d * pd[jpd - 4];
                  zuu[i - 1] = aa * pd[jpd - 3] + act2 * pd[jpd - 2] + cc * pd[jpd - 1];
                  zuv[i - 1] = ab * pd[jpd - 3] + adbc * pd[jpd - 2] + cd * pd[jpd - 1];
                  zvv[i - 1] = bb * pd[jpd - 3] + bdt2 * pd[jpd - 2] + dd * pd[jpd - 1];
                  /* L60: */
                }
              /* CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. */
              p00 = z[0];
              p10 = zu[0];
              p01 = zv[0];
              p20 = zuu[0] * .5;
              p11 = zuv[0];
              p02 = zvv[0] * .5;
              h1 = z[1] - p00 - p01 - p02;
              h2 = zv[1] - p01 - zvv[0];
              h3 = zvv[1] - zvv[0];
              p03 = h1 * 10. - h2 * 4. + h3 * .5;
              p04 = h1 * -15. + h2 * 7. - h3;
              p05 = h1 * 6. - h2 * 3. + h3 * .5;
              h1 = zu[1] - p10 - p11;
              h2 = zuv[1] - p11;
              p12 = h1 * 3. - h2;
              p13 = h1 * -2. + h2;
              p21 = 0.;
              p23 = -zuu[1] + zuu[0];
              p22 = p23 * -1.5;
              *itpv = it0;
            }
          /* CONVERTS XII AND YII TO U-V SYSTEM. */
          dx = *xii - x0;
          dy = *yii - y0;
          u = ap * dx + bp * dy;
          v = cp * dx + dp * dy;
          /* EVALUATES THE POLYNOMIAL. */
          p0 = p00 + v * (p01 + v * (p02 + v * (p03 + v * (p04 + v * p05))));
          p1 = p10 + v * (p11 + v * (p12 + v * p13));
          p2 = p20 + v * (p21 + v * (p22 + v * p23));
          *zii = p0 + u * (p1 + u * p2);
        }
      else
        {
          /* CALCULATION OF ZII BY EXTRAPOLATION IN THE TRIANGLE. */
          /* CHECKS IF THE NECESSARY COEFFICIENTS HAVE BEEN CALCULATED. */
          if (it0 != *itpv)
            {
              /* LOADS COORDINATE AND PARTIAL DERIVATIVE VALUES AT THE VERTEX */
              /* OF THE TRIANGLE. */
              jipl = il2 * 3 - 2;
              idp = ipl[jipl - 1];
              x[0] = xd[idp - 1];
              y[0] = yd[idp - 1];
              z[0] = zd[idp - 1];
              jpdd = (idp - 1) * 5;
              for (kpd = 1; kpd <= 5; ++kpd)
                {
                  ++jpdd;
                  pd[kpd - 1] = pdd[jpdd - 1];
                  /* L70: */
                }
              /* CALCULATES THE COEFFICIENTS OF THE POLYNOMIAL. */
              p00 = z[0];
              p10 = pd[0];
              p01 = pd[1];
              p20 = pd[2] * .5;
              p11 = pd[3];
              p02 = pd[4] * .5;
              *itpv = it0;
            }
          /* CONVERTS XII AND YII TO U-V SYSTEM. */
          u = *xii - x[0];
          v = *yii - y[0];
          /* EVALUATES THE POLYNOMIAL. */
          p0 = p00 + v * (p01 + v * p02);
          p1 = p10 + v * p11;
          *zii = p0 + u * (p1 + u * p20);
        }
    }
  return 0;
}

static int idxchg(double *x, double *y, int *i1, int *i2, int *i3, int *i4)
{
  Integer ret_val;
  Real r1, r2;
  Real a1sq, b1sq, c1sq, c2sq, a3sq, b2sq, b3sq, a4sq, b4sq, a2sq, c4sq, c3sq;
  Real u1, u2, u3, x1, y1, x2, y2, x3, y3, x4, y4, u4;
  Integer idx;
  Real s1sq, s2sq, s3sq, s4sq;

  /* THIS FUNCTION DETERMINES WHETHER OR NOT THE EXCHANGE OF TWO */
  /* TRIANGLES IS NECESSARY ON THE BASIS OF MAX-MIN-ANGLE CRITERION */
  /* BY C. L. LAWSON. */
  /* THE INPUT PARAMETERS ARE */
  /*     X,Y = ARRAYS CONTAINING THE COORDINATES OF THE DATA */
  /*           POINTS, */
  /*     I1,I2,I3,I4 = POINT NUMBERS OF FOUR POINTS P1, P2, */
  /*           P3, AND P4 THAT FORM A QUADRILATERAL WITH P3 */
  /*           AND P4 CONNECTED DIAGONALLY. */
  /* THIS FUNCTION RETURNS AN INTEGER VALUE 1 (ONE) WHEN AN EX- */
  /* CHANGE IS NECESSARY, AND 0 (ZERO) OTHERWISE. */

  x1 = x[*i1 - 1];
  y1 = y[*i1 - 1];
  x2 = x[*i2 - 1];
  y2 = y[*i2 - 1];
  x3 = x[*i3 - 1];
  y3 = y[*i3 - 1];
  x4 = x[*i4 - 1];
  y4 = y[*i4 - 1];
  /* CALCULATION */
  idx = 0;
  u3 = (y2 - y3) * (x1 - x3) - (x2 - x3) * (y1 - y3);
  u4 = (y1 - y4) * (x2 - x4) - (x1 - x4) * (y2 - y4);
  if (u3 * u4 > 0.)
    {
      u1 = (y3 - y1) * (x4 - x1) - (x3 - x1) * (y4 - y1);
      u2 = (y4 - y2) * (x3 - x2) - (x4 - x2) * (y3 - y2);
      r1 = x1 - x3;
      r2 = y1 - y3;
      a1sq = b3sq = r1 * r1 + r2 * r2;
      r1 = x4 - x1;
      r2 = y4 - y1;
      b1sq = a4sq = r1 * r1 + r2 * r2;
      r1 = x3 - x4;
      r2 = y3 - y4;
      c1sq = c2sq = r1 * r1 + r2 * r2;
      r1 = x2 - x4;
      r2 = y2 - y4;
      a2sq = b4sq = r1 * r1 + r2 * r2;
      r1 = x3 - x2;
      r2 = y3 - y2;
      b2sq = a3sq = r1 * r1 + r2 * r2;
      r1 = x2 - x1;
      r2 = y2 - y1;
      c3sq = c4sq = r1 * r1 + r2 * r2;
      s1sq = u1 * u1 / (c1sq * max(a1sq, b1sq));
      s2sq = u2 * u2 / (c2sq * max(a2sq, b2sq));
      s3sq = u3 * u3 / (c3sq * max(a3sq, b3sq));
      s4sq = u4 * u4 / (c4sq * max(a4sq, b4sq));
      if (min(s1sq, s2sq) < min(s3sq, s4sq))
        {
          idx = 1;
        }
    }
  ret_val = idx;
  return ret_val;
}

static int idtang(int *ndp, double *xd, double *yd, int *nt, int *ipt, int *nl, int *ipl, int *iwl, int *iwp,
                  double *wk)
{
  Real ratio = 1e-12;
  Integer nrep = 100;
  Real x1, y1, ar, r1, r2;
  Integer ip, jp;
  Real dx, dy;
  Integer it, ip1, ip2, jp1, jp2, ip3, nl0, nt0, ilf, jpc;
  Real dx21, dy21;
  Integer nlf, itf[2], nln, nsh, ntf, jwl, its, ndp0, ipl1, ipl2;
  Integer jlt3, ipt1, ipt2, ipt3, nlt3, jwl1, itt3, ntt3, nlfc, ip1p1;
  Real dsq12, armn;
  Integer irep;
  Real dsqi;
  Integer jp2t3, jp3t3, jpmn;
  Real dxmn, dymn, xdmp, ydmp, armx;
  Integer ipti, it1t3, it2t3, jpmx;
  Real dxmx, dymx;
  Integer ndpm1, ilft2, iplj1, iplj2, ipmn1, ipmn2, ipti1, ipti2;
  Integer nlft2, nlnt3, nsht3, itt3r;
  Real dsqmn;
  Integer ntt3p3;
  Real dsqmx;
  Integer jwl1mn;

  /* THIS SUBROUTINE PERFORMS TRIANGULATION.  IT DIVIDES THE X-Y */
  /* PLANE INTO A NUMBER OF TRIANGLES ACCORDING TO GIVEN DATA */
  /* POINTS IN THE PLANE, DETERMINES LINE SEGMENTS THAT FORM THE */
  /* BORDER OF DATA AREA, AND DETERMINES THE TRIANGLE NUMBERS */
  /* CORRESPONDING TO THE BORDER LINE SEGMENTS. */
  /* AT COMPLETION, POINT NUMBERS OF THE VERTEXES OF EACH TRIANGLE */
  /* ARE LISTED COUNTER-CLOCKWISE.  POINT NUMBERS OF THE END POINTS */
  /* OF EACH BORDER LINE SEGMENT ARE LISTED COUNTER-CLOCKWISE, */
  /* LISTING ORDER OF THE LINE SEGMENTS BEING COUNTER-CLOCKWISE. */
  /* THIS SUBROUTINE CALLS THE IDXCHG FUNCTION. */
  /* THE INPUT PARAMETERS ARE */
  /*     NDP = NUMBER OF DATA POINTS, */
  /*     XD  = ARRAY OF DIMENSION NDP CONTAINING THE */
  /*           X COORDINATES OF THE DATA POINTS, */
  /*     YD  = ARRAY OF DIMENSION NDP CONTAINING THE */
  /*           Y COORDINATES OF THE DATA POINTS. */
  /* THE OUTPUT PARAMETERS ARE */
  /*     NT  = NUMBER OF TRIANGLES, */
  /*     IPT = INTEGER ARRAY OF DIMENSION 6*NDP-15, WHERE THE */
  /*           POINT NUMBERS OF THE VERTEXES OF THE (IT)TH */
  /*           TRIANGLE ARE TO BE STORED AS THE (3*IT-2)ND, */
  /*           (3*IT-1)ST, AND (3*IT)TH ELEMENTS, */
  /*           IT=1,2,...,NT, */
  /*     NL  = NUMBER OF BORDER LINE SEGMENTS, */
  /*     IPL = INTEGER ARRAY OF DIMENSION 6*NDP, WHERE THE */
  /*           POINT NUMBERS OF THE END POINTS OF THE (IL)TH */
  /*           BORDER LINE SEGMENT AND ITS RESPECTIVE TRIANGLE */
  /*           NUMBER ARE TO BE STORED AS THE (3*IL-2)ND, */
  /*           (3*IL-1)ST, AND (3*IL)TH ELEMENTS, */
  /*           IL=1,2,..., NL. */
  /* THE OTHER PARAMETERS ARE */
  /*     IWL = INTEGER ARRAY OF DIMENSION 18*NDP USED */
  /*           INTERNALLY AS A WORK AREA, */
  /*     IWP = INTEGER ARRAY OF DIMENSION NDP USED */
  /*           INTERNALLY AS A WORK AREA, */
  /*     WK  = ARRAY OF DIMENSION NDP USED INTERNALLY AS A */
  /*           WORK AREA. */

  /* PRELIMINARY PROCESSING */
  nlnt3 = 0;
  nln = 0;
  ndp0 = *ndp;
  ndpm1 = ndp0 - 1;
  if (ndp0 < 4)
    {
      /* ERROR EXIT */
      fprintf(stderr,
              " ***   NDP LESS THAN 4.\n"
              "   NDP =%5d\n",
              ndp0);
    }
  else
    {
      /* DETERMINES THE CLOSEST PAIR OF DATA POINTS AND THEIR MIDPOINT. */
      r1 = xd[1] - xd[0];
      r2 = yd[1] - yd[0];
      dsqmn = r1 * r1 + r2 * r2;
      ipmn1 = 1;
      ipmn2 = 2;
      for (ip1 = 1; ip1 <= ndpm1; ++ip1)
        {
          x1 = xd[ip1 - 1];
          y1 = yd[ip1 - 1];
          ip1p1 = ip1 + 1;
          for (ip2 = ip1p1; ip2 <= ndp0; ++ip2)
            {
              r1 = xd[ip2 - 1] - x1;
              r2 = yd[ip2 - 1] - y1;
              dsqi = r1 * r1 + r2 * r2;
              if (fabs(dsqi) <= 1e-12)
                {
                  goto L30;
                }
              else if (dsqi < dsqmn)
                {
                  dsqmn = dsqi;
                  ipmn1 = ip1;
                  ipmn2 = ip2;
                }
              /* L20: */
            }
          /* L10: */
        }
      dsq12 = dsqmn;
      xdmp = (xd[ipmn1 - 1] + xd[ipmn2 - 1]) / 2.;
      ydmp = (yd[ipmn1 - 1] + yd[ipmn2 - 1]) / 2.;
      /* SORTS THE OTHER (NDP-2) DATA POINTS IN ASCENDING ORDER OF */
      /* DISTANCE FROM THE MIDPOINT AND STORES THE SORTED DATA POINT */
      /* NUMBERS IN THE IWP ARRAY. */
      jp1 = 2;
      for (ip1 = 1; ip1 <= ndp0; ++ip1)
        {
          if (ip1 != ipmn1 && ip1 != ipmn2)
            {
              ++jp1;
              iwp[jp1 - 1] = ip1;
              r1 = xd[ip1 - 1] - xdmp;
              r2 = yd[ip1 - 1] - ydmp;
              wk[jp1 - 1] = r1 * r1 + r2 * r2;
            }
          /* L40: */
        }
      for (jp1 = 3; jp1 <= ndpm1; ++jp1)
        {
          dsqmn = wk[jp1 - 1];
          jpmn = jp1;
          for (jp2 = jp1; jp2 <= ndp0; ++jp2)
            {
              if (wk[jp2 - 1] < dsqmn)
                {
                  dsqmn = wk[jp2 - 1];
                  jpmn = jp2;
                }
              /* L60: */
            }
          its = iwp[jp1 - 1];
          iwp[jp1 - 1] = iwp[jpmn - 1];
          iwp[jpmn - 1] = its;
          wk[jpmn - 1] = wk[jp1 - 1];
          /* L50: */
        }
      /* IF NECESSARY, MODIFIES THE ORDERING IN SUCH A WAY THAT THE */
      /* FIRST THREE DATA POINTS ARE NOT COLLINEAR. */
      ar = dsq12 * ratio;
      x1 = xd[ipmn1 - 1];
      y1 = yd[ipmn1 - 1];
      dx21 = xd[ipmn2 - 1] - x1;
      dy21 = yd[ipmn2 - 1] - y1;
      for (jp = 3; jp <= ndp0; ++jp)
        {
          ip = iwp[jp - 1];
          if ((r1 = (yd[ip - 1] - y1) * dx21 - (xd[ip - 1] - x1) * dy21, fabs(r1)) > ar)
            {
              goto L80;
            }
          /* L70: */
        }
      fprintf(stderr,
              " ***   ALL COLLINEAR DATA POINTS.\n"
              "   NDP =%5d\n",
              ndp0);
      goto L90;
    L80:
      if (jp != 3)
        {
          jpmx = jp;
          jp = jpmx + 1;
          for (jpc = 4; jpc <= jpmx; ++jpc)
            {
              --jp;
              iwp[jp - 1] = iwp[jp - 2];
              /* L100: */
            }
          iwp[2] = ip;
        }
      /* FORMS THE FIRST TRIANGLE.  STORES POINT NUMBERS OF THE VER- */
      /* TEXES OF THE TRIANGLE IN THE IPT ARRAY, AND STORES POINT NUM- */
      /* BERS OF THE BORDER LINE SEGMENTS AND THE TRIANGLE NUMBER IN */
      /* THE IPL ARRAY. */
      ip1 = ipmn1;
      ip2 = ipmn2;
      ip3 = iwp[2];
      if ((yd[ip3 - 1] - yd[ip1 - 1]) * (xd[ip2 - 1] - xd[ip1 - 1]) -
              (xd[ip3 - 1] - xd[ip1 - 1]) * (yd[ip2 - 1] - yd[ip1 - 1]) <
          0.)
        {
          ip1 = ipmn2;
          ip2 = ipmn1;
        }
      nt0 = 1;
      ntt3 = 3;
      ipt[0] = ip1;
      ipt[1] = ip2;
      ipt[2] = ip3;
      nl0 = 3;
      nlt3 = 9;
      ipl[0] = ip1;
      ipl[1] = ip2;
      ipl[2] = 1;
      ipl[3] = ip2;
      ipl[4] = ip3;
      ipl[5] = 1;
      ipl[6] = ip3;
      ipl[7] = ip1;
      ipl[8] = 1;
      /* ADDS THE REMAINING (NDP-3) DATA POINTS, ONE BY ONE. */
      for (jp1 = 4; jp1 <= ndp0; ++jp1)
        {
          ip1 = iwp[jp1 - 1];
          x1 = xd[ip1 - 1];
          y1 = yd[ip1 - 1];
          /* - DETERMINES THE VISIBLE BORDER LINE SEGMENTS. */
          ip2 = ipl[0];
          jpmn = 1;
          dxmn = xd[ip2 - 1] - x1;
          dymn = yd[ip2 - 1] - y1;
          r1 = dxmn;
          r2 = dymn;
          dsqmn = r1 * r1 + r2 * r2;
          armn = dsqmn * ratio;
          jpmx = 1;
          dxmx = dxmn;
          dymx = dymn;
          dsqmx = dsqmn;
          armx = armn;
          for (jp2 = 2; jp2 <= nl0; ++jp2)
            {
              ip2 = ipl[jp2 * 3 - 3];
              dx = xd[ip2 - 1] - x1;
              dy = yd[ip2 - 1] - y1;
              ar = dy * dxmn - dx * dymn;
              if (ar <= armn)
                {
                  r1 = dx;
                  r2 = dy;
                  dsqi = r1 * r1 + r2 * r2;
                  if (ar < -armn || dsqi < dsqmn)
                    {
                      jpmn = jp2;
                      dxmn = dx;
                      dymn = dy;
                      dsqmn = dsqi;
                      armn = dsqmn * ratio;
                    }
                }
              ar = dy * dxmx - dx * dymx;
              if (ar >= -armx)
                {
                  r1 = dx;
                  r2 = dy;
                  dsqi = r1 * r1 + r2 * r2;
                  if (ar > armx || dsqi < dsqmx)
                    {
                      jpmx = jp2;
                      dxmx = dx;
                      dymx = dy;
                      dsqmx = dsqi;
                      armx = dsqmx * ratio;
                    }
                }
              /* L120: */
            }
          if (jpmx < jpmn)
            {
              jpmx += nl0;
            }
          nsh = jpmn - 1;
          if (nsh > 0)
            {
              /* - SHIFTS (ROTATES) THE IPL ARRAY TO HAVE THE INVISIBLE BORDER */
              /* - LINE SEGMENTS CONTAINED IN THE FIRST PART OF THE IPL ARRAY. */
              nsht3 = nsh * 3;
              for (jp2t3 = 3; jp2t3 <= nsht3; jp2t3 += 3)
                {
                  jp3t3 = jp2t3 + nlt3;
                  ipl[jp3t3 - 3] = ipl[jp2t3 - 3];
                  ipl[jp3t3 - 2] = ipl[jp2t3 - 2];
                  ipl[jp3t3 - 1] = ipl[jp2t3 - 1];
                  /* L130: */
                }
              for (jp2t3 = 3; jp2t3 <= nlt3; jp2t3 += 3)
                {
                  jp3t3 = jp2t3 + nsht3;
                  ipl[jp2t3 - 3] = ipl[jp3t3 - 3];
                  ipl[jp2t3 - 2] = ipl[jp3t3 - 2];
                  ipl[jp2t3 - 1] = ipl[jp3t3 - 1];
                  /* L140: */
                }
              jpmx -= nsh;
            }
          /* - ADDS TRIANGLES TO THE IPT ARRAY, UPDATES BORDER LINE */
          /* - SEGMENTS IN THE IPL ARRAY, AND SETS FLAGS FOR THE BORDER */
          /* - LINE SEGMENTS TO BE REEXAMINED IN THE IWL ARRAY. */
          jwl = 0;
          for (jp2 = jpmx; jp2 <= nl0; ++jp2)
            {
              jp2t3 = jp2 * 3;
              ipl1 = ipl[jp2t3 - 3];
              ipl2 = ipl[jp2t3 - 2];
              it = ipl[jp2t3 - 1];
              /* - - ADDS A TRIANGLE TO THE IPT ARRAY. */
              ++nt0;
              ntt3 += 3;
              ipt[ntt3 - 3] = ipl2;
              ipt[ntt3 - 2] = ipl1;
              ipt[ntt3 - 1] = ip1;
              /* - - UPDATES BORDER LINE SEGMENTS IN THE IPL ARRAY. */
              if (jp2 == jpmx)
                {
                  ipl[jp2t3 - 2] = ip1;
                  ipl[jp2t3 - 1] = nt0;
                }
              if (jp2 == nl0)
                {
                  nln = jpmx + 1;
                  nlnt3 = nln * 3;
                  ipl[nlnt3 - 3] = ip1;
                  ipl[nlnt3 - 2] = ipl[0];
                  ipl[nlnt3 - 1] = nt0;
                }
              /* - - DETERMINES THE VERTEX THAT DOES NOT LIE ON THE BORDER */
              /* - - LINE SEGMENTS. */
              itt3 = it * 3;
              ipti = ipt[itt3 - 3];
              if (ipti == ipl1 || ipti == ipl2)
                {
                  ipti = ipt[itt3 - 2];
                  if (ipti == ipl1 || ipti == ipl2)
                    {
                      ipti = ipt[itt3 - 1];
                    }
                }
              /* - - CHECKS IF THE EXCHANGE IS NECESSARY. */
              if (idxchg(&xd[0], &yd[0], &ip1, &ipti, &ipl1, &ipl2) != 0)
                {
                  /* - - MODIFIES THE IPT ARRAY WHEN NECESSARY. */
                  ipt[itt3 - 3] = ipti;
                  ipt[itt3 - 2] = ipl1;
                  ipt[itt3 - 1] = ip1;
                  ipt[ntt3 - 2] = ipti;
                  if (jp2 == jpmx)
                    {
                      ipl[jp2t3 - 1] = it;
                    }
                  if (jp2 == nl0 && ipl[2] == it)
                    {
                      ipl[2] = nt0;
                    }
                  /* - - SETS FLAGS IN THE IWL ARRAY. */
                  jwl += 4;
                  iwl[jwl - 4] = ipl1;
                  iwl[jwl - 3] = ipti;
                  iwl[jwl - 2] = ipti;
                  iwl[jwl - 1] = ipl2;
                }
              /* L150: */
            }
          nl0 = nln;
          nlt3 = nlnt3;
          nlf = jwl / 2;
          if (nlf != 0)
            {
              /* - IMPROVES TRIANGULATION. */
              ntt3p3 = ntt3 + 3;
              for (irep = 1; irep <= nrep; ++irep)
                {
                  for (ilf = 1; ilf <= nlf; ++ilf)
                    {
                      ilft2 = ilf * 2;
                      ipl1 = iwl[ilft2 - 2];
                      ipl2 = iwl[ilft2 - 1];
                      /* - - LOCATES IN THE IPT ARRAY TWO TRIANGLES ON BOTH SIDES OF */
                      /* - - THE FLAGGED LINE SEGMENT. */
                      ntf = 0;
                      for (itt3r = 3; itt3r <= ntt3; itt3r += 3)
                        {
                          itt3 = ntt3p3 - itt3r;
                          ipt1 = ipt[itt3 - 3];
                          ipt2 = ipt[itt3 - 2];
                          ipt3 = ipt[itt3 - 1];
                          if (ipl1 == ipt1 || ipl1 == ipt2 || ipl1 == ipt3)
                            {
                              if (ipl2 == ipt1 || ipl2 == ipt2 || ipl2 == ipt3)
                                {
                                  ++ntf;
                                  itf[ntf - 1] = itt3 / 3;
                                  if (ntf == 2)
                                    {
                                      goto L190;
                                    }
                                }
                            }
                          /* L180: */
                        }
                      if (ntf < 2)
                        {
                          goto L170;
                        }
                      /* - - DETERMINES THE VERTEXES OF THE TRIANGLES THAT DO NOT LIE */
                      /* - - ON THE LINE SEGMENT. */
                    L190:
                      it1t3 = itf[0] * 3;
                      ipti1 = ipt[it1t3 - 3];
                      if (ipti1 == ipl1 || ipti1 == ipl2)
                        {
                          ipti1 = ipt[it1t3 - 2];
                          if (ipti1 == ipl1 || ipti1 == ipl2)
                            {
                              ipti1 = ipt[it1t3 - 1];
                            }
                        }
                      it2t3 = itf[1] * 3;
                      ipti2 = ipt[it2t3 - 3];
                      if (ipti2 == ipl1 || ipti2 == ipl2)
                        {
                          ipti2 = ipt[it2t3 - 2];
                          if (ipti2 == ipl1 || ipti2 == ipl2)
                            {
                              ipti2 = ipt[it2t3 - 1];
                            }
                        }
                      /* - - CHECKS IF THE EXCHANGE IS NECESSARY. */
                      if (idxchg(&xd[0], &yd[0], &ipti1, &ipti2, &ipl1, &ipl2) != 0)
                        {
                          /* - - MODIFIES THE IPT ARRAY WHEN NECESSARY. */
                          ipt[it1t3 - 3] = ipti1;
                          ipt[it1t3 - 2] = ipti2;
                          ipt[it1t3 - 1] = ipl1;
                          ipt[it2t3 - 3] = ipti2;
                          ipt[it2t3 - 2] = ipti1;
                          ipt[it2t3 - 1] = ipl2;
                          /* - - SETS NEW FLAGS. */
                          jwl += 8;
                          iwl[jwl - 8] = ipl1;
                          iwl[jwl - 7] = ipti1;
                          iwl[jwl - 6] = ipti1;
                          iwl[jwl - 5] = ipl2;
                          iwl[jwl - 4] = ipl2;
                          iwl[jwl - 3] = ipti2;
                          iwl[jwl - 2] = ipti2;
                          iwl[jwl - 1] = ipl1;
                          for (jlt3 = 3; jlt3 <= nlt3; jlt3 += 3)
                            {
                              iplj1 = ipl[jlt3 - 3];
                              iplj2 = ipl[jlt3 - 2];
                              if ((iplj1 == ipl1 && iplj2 == ipti2) || (iplj2 == ipl1 && iplj1 == ipti2))
                                {
                                  ipl[jlt3 - 1] = itf[0];
                                }
                              if ((iplj1 == ipl2 && iplj2 == ipti1) || (iplj2 == ipl2 && iplj1 == ipti1))
                                {
                                  ipl[jlt3 - 1] = itf[1];
                                }
                              /* L200: */
                            }
                        }
                    L170:;
                    }
                  nlfc = nlf;
                  nlf = jwl / 2;
                  if (nlf == nlfc)
                    {
                      goto L110;
                    }
                  else
                    {
                      /* - - RESETS THE IWL ARRAY FOR THE NEXT ROUND. */
                      jwl = 0;
                      jwl1mn = (nlfc + 1) * 2;
                      nlft2 = nlf * 2;
                      for (jwl1 = jwl1mn; jwl1 <= nlft2; jwl1 += 2)
                        {
                          jwl += 2;
                          iwl[jwl - 2] = iwl[jwl1 - 2];
                          iwl[jwl - 1] = iwl[jwl1 - 1];
                          /* L210: */
                        }
                      nlf = jwl / 2;
                    }
                  /* L160: */
                }
            }
        L110:;
        }
      /* REARRANGES THE IPT ARRAY SO THAT THE VERTEXES OF EACH TRIANGLE */
      /* ARE LISTED COUNTER-CLOCKWISE. */
      for (itt3 = 3; itt3 <= ntt3; itt3 += 3)
        {
          ip1 = ipt[itt3 - 3];
          ip2 = ipt[itt3 - 2];
          ip3 = ipt[itt3 - 1];
          if ((yd[ip3 - 1] - yd[ip1 - 1]) * (xd[ip2 - 1] - xd[ip1 - 1]) -
                  (xd[ip3 - 1] - xd[ip1 - 1]) * (yd[ip2 - 1] - yd[ip1 - 1]) <
              0.)
            {
              ipt[itt3 - 3] = ip2;
              ipt[itt3 - 2] = ip1;
            }
          /* L220: */
        }
      *nt = nt0;
      *nl = nl0;
      return 0;
    L30:
      fprintf(stderr,
              " ***   IDENTICAL DATA POINTS.\n"
              "   NDP =%5d   IP1 =%5d   IP2 =%5d   XD=%g   YD=%g\n",
              ndp0, ip1, ip2, x1, y1);
    }
L90:
  fprintf(stderr, " ERROR DETECTED IN ROUTINE   IDTANG.\n");
  *nt = 0;
  return 0;
}

static int idlin(double *xd, double *yd, double *zd, int *nt, int *iwk, double *wk)
{
  Real x1, y1, z1, x2, y2, z2, x3, y3, z3;
  Integer ip1, ip2, ip3, itri, ipoint;

  /* THIS ROUTINE GENERATES THE COORDINATES USED IN A LINEAR INTERPOLATION */
  /* OF THE TRIANGLES CREATED FROM IRREGULARLY DISTRIBUTED DATA. */
  /*   LOOP FOR ALL TRIANGLES */
  /* Parameter adjustments */

  for (itri = 1; itri <= *nt; ++itri)
    {
      /* GET THE POINTS OF THE TRIANGLE */
      ipoint = (itri - 1) * 3;
      ip1 = iwk[ipoint] - 1;
      ip2 = iwk[ipoint + 1] - 1;
      ip3 = iwk[ipoint + 2] - 1;
      /* GET THE VALUES AT THE TRIANBGLE POINTS */
      x1 = xd[ip1];
      y1 = yd[ip1];
      z1 = zd[ip1];
      x2 = xd[ip2];
      y2 = yd[ip2];
      z2 = zd[ip2];
      x3 = xd[ip3];
      y3 = yd[ip3];
      z3 = zd[ip3];
      /* COMPUTE THE INTERPLOATING COEFICIENTS */
      wk[ipoint] = (y2 - y1) * (z3 - z1) - (y3 - y1) * (z2 - z1);
      wk[ipoint + 1] = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1);
      wk[ipoint + 2] = (x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1);
      /* L10: */
    }
  return 0;
}

static int idlcom(double *x, double *y, double *z, int *itri, double *xd, double *yd, double *zd, int *nt, int *iwk,
                  double *wk)
{
  Real x1, y1, z1;
  Integer iv, ipoint;

  /* COMPUTE A Z VALUE FOR A GIVEN X,Y VALUE */
  /* IF OUTSIDE CONVEX HULL DON'T COMPUTE A VALUE */

  if (*itri <= *nt)
    {
      ipoint = (*itri - 1) * 3;
      iv = iwk[ipoint] - 1;
      x1 = *x - xd[iv];
      y1 = *y - yd[iv];
      z1 = zd[iv];
      /* COMPUTE THE Z VALUE */
      *z = (wk[ipoint] * x1 + wk[ipoint + 1] * y1) / wk[ipoint + 2] + z1;
    }
  return 0;
}

void idsfft(int *md, int *ncp, int *ndp, double *xd, double *yd, double *zd, int *nxi, int *nyi, double *xi, double *yi,
            double *zi, int *iwk, double *wk)
{
  Integer nl, nt, md0, il1, il2, iti, ixi, izi, iyi, ncp0, ndp0;
  Integer ngp0, ngp1, nxi0, nyi0, jigp, jngp, nngp, itpv;
  Integer jwipc, jwigp, jwipl, ncppv, ndppv, jwngp, jwiwl, jwipt;
  Integer jwiwp, nxipv, nyipv, jig0mn, jig1mn, jig0mx, jig1mx, jwigp0, jwngp0;
  Integer linear;

  /* THIS SUBROUTINE PERFORMS SMOOTH SURFACE FITTING WHEN THE PRO- */
  /* JECTIONS OF THE DATA POINTS IN THE X-Y PLANE ARE IRREGULARLY */
  /* DISTRIBUTED IN THE PLANE. */
  /* THE INPUT PARAMETERS ARE */
  /*     MD  = MODE OF COMPUTATION (MUST BE 1, 2, OR 3), */
  /*         = 1 FOR NEW NCP AND/OR NEW XD-YD, */
  /*         = 2 FOR OLD NCP, OLD XD-YD, NEW XI-YI, */
  /*         = 3 FOR OLD NCP, OLD XD-YD, OLD XI-YI, */
  /*     NCP = NUMBER OF ADDITIONAL DATA POINTS USED FOR ESTI- */
  /*           MATING PARTIAL DERIVATIVES AT EACH DATA POINT */
  /*           (MUST BE 2 OR GREATER, BUT SMALLER THAN NDP), */
  /*     NDP = NUMBER OF DATA POINTS (MUST BE 4 OR GREATER), */
  /*     XD  = ARRAY OF DIMENSION NDP CONTAINING THE X */
  /*           COORDINATES OF THE DATA POINTS, */
  /*     YD  = ARRAY OF DIMENSION NDP CONTAINING THE Y */
  /*           COORDINATES OF THE DATA POINTS, */
  /*     ZD  = ARRAY OF DIMENSION NDP CONTAINING THE Z */
  /*           COORDINATES OF THE DATA POINTS, */
  /*     NXI = NUMBER OF OUTPUT GRID POINTS IN THE X COORDINATE */
  /*           (MUST BE 1 OR GREATER), */
  /*     NYI = NUMBER OF OUTPUT GRID POINTS IN THE Y COORDINATE */
  /*           (MUST BE 1 OR GREATER), */
  /*     XI  = ARRAY OF DIMENSION NXI CONTAINING THE X */
  /*           COORDINATES OF THE OUTPUT GRID POINTS, */
  /*     YI  = ARRAY OF DIMENSION NYI CONTAINING THE Y */
  /*           COORDINATES OF THE OUTPUT GRID POINTS. */
  /* THE OUTPUT PARAMETER IS */
  /*     ZI  = DOUBLY-DIMENSIONED ARRAY OF DIMENSION (NXI,NYI), */
  /*           WHERE THE INTERPOLATED Z VALUES AT THE OUTPUT */
  /*           GRID POINTS ARE TO BE STORED. */
  /* THE OTHER PARAMETERS ARE */
  /*     IWK = INTEGER ARRAY OF DIMENSION */
  /*              MAX0(31,27+NCP)*NDP+NXI*NYI */
  /*           USED INTERNALLY AS A WORK AREA, */
  /*     WK  = ARRAY OF DIMENSION 6*(NDP+1) USED INTERNALLY AS A */
  /*           WORK AREA. */
  /* THE VERY FIRST CALL TO THIS SUBROUTINE AND THE CALL WITH A NEW */
  /* NCP VALUE, A NEW NDP VALUE, AND/OR NEW CONTENTS OF THE XD AND */
  /* YD ARRAYS MUST BE MADE WITH MD=1.  THE CALL WITH MD=2 MUST BE */
  /* PRECEDED BY ANOTHER CALL WITH THE SAME NCP AND NDP VALUES AND */
  /* WITH THE SAME CONTENTS OF THE XD AND YD ARRAYS.  THE CALL WITH */
  /* MD=3 MUST BE PRECEDED BY ANOTHER CALL WITH THE SAME NCP, NDP, */
  /* NXI, AND NYI VALUES AND WITH THE SAME CONTENTS OF THE XD, YD, */
  /* XI, AND YI ARRAYS.  BETWEEN THE CALL WITH MD=2 OR MD=3 AND ITS */
  /* PRECEDING CALL, THE IWK AND WK ARRAYS MUST NOT BE DISTURBED. */
  /* USE OF A VALUE BETWEEN 3 AND 5 (INCLUSIVE) FOR NCP IS RECOM- */
  /* MENDED UNLESS THERE ARE EVIDENCES THAT DICTATE OTHERWISE. */
  /* THIS SUBROUTINE CALLS THE IDCLDP, IDGRID, IDPDRV, IDPTIP, AND */
  /* IDTANG SUBROUTINES. */

  md0 = *md;
  ncp0 = *ncp;
  ndp0 = *ndp;
  nxi0 = *nxi;
  nyi0 = *nyi;
  linear = 0;
  if (*ndp > 100)
    {
      linear = 1;
    }
  /* ERROR CHECK.  (FOR MD=1,2,3) */
  if (md0 >= 1 && md0 <= 3)
    {
      if (ncp0 >= 2 && ncp0 < ndp0)
        {
          if (ndp0 >= 4)
            {
              if (nxi0 >= 1 && nyi0 >= 1)
                {
                  if (md0 >= 2)
                    {
                      ncppv = iwk[0];
                      ndppv = iwk[1];
                      if (ncp0 != ncppv)
                        {
                          goto L10;
                        }
                      else if (ndp0 != ndppv)
                        {
                          goto L10;
                        }
                    }
                  else
                    {
                      iwk[0] = ncp0;
                      iwk[1] = ndp0;
                    }
                  if (md0 >= 3)
                    {
                      nxipv = iwk[2];
                      nyipv = iwk[3];
                      if (nxi0 != nxipv)
                        {
                          goto L10;
                        }
                      else if (nyi0 != nyipv)
                        {
                          goto L10;
                        }
                    }
                  else
                    {
                      iwk[2] = nxi0;
                      iwk[3] = nyi0;
                    }
                  /* ALLOCATION OF STORAGE AREAS IN THE IWK ARRAY.  (FOR MD=1,2,3) */
                  jwipt = 16;
                  jwiwl = ndp0 * 6 + 1;
                  jwngp0 = jwiwl - 1;
                  jwipl = ndp0 * 24 + 1;
                  jwiwp = ndp0 * 30 + 1;
                  jwipc = ndp0 * 27 + 1;
                  jwigp0 = max(31, ncp0 + 27) * ndp0;
                  /* TRIANGULATES THE X-Y PLANE.  (FOR MD=1) */
                  if (md0 <= 1)
                    {
                      idtang(&ndp0, &xd[0], &yd[0], &nt, &iwk[jwipt - 1], &nl, &iwk[jwipl - 1], &iwk[jwiwl - 1],
                             &iwk[jwiwp - 1], &wk[0]);
                      iwk[4] = nt;
                      iwk[5] = nl;
                      if (nt == 0)
                        {
                          return;
                        }
                    }
                  /* DETERMINES NCP POINTS CLOSEST TO EACH DATA POINT.  (FOR MD=1) */
                  if (md0 <= 1)
                    {
                      idcldp(&ndp0, &xd[0], &yd[0], &ncp0, &iwk[jwipc - 1]);
                      if (iwk[jwipc - 1] == 0)
                        {
                          return;
                        }
                    }
                  /* SORTS OUTPUT GRID POINTS IN ASCENDING ORDER OF THE TRIANGLE */
                  /* NUMBER AND THE BORDER LINE SEGMENT NUMBER.  (FOR MD=1,2) */
                  if (md0 != 3)
                    {
                      idgrid(&xd[0], &yd[0], &nt, &iwk[jwipt - 1], &nl, &iwk[jwipl - 1], &nxi0, &nyi0, &xi[0], &yi[0],
                             &iwk[jwngp0], &iwk[jwigp0]);
                    }
                  if (linear)
                    {
                      /* FIND THE COEFFICENTS FOR LINER INTERPOLATION OF EACH TRIANGLE */
                      idlin(&xd[0], &yd[0], &zd[0], &nt, &iwk[jwipt - 1], &wk[0]);
                    }
                  else
                    {
                      /* ESTIMATES PARTIAL DERIVATIVES AT ALL DATA POINTS. */
                      /* (FOR MD=1,2,3) */
                      idpdrv(&ndp0, &xd[0], &yd[0], &zd[0], &ncp0, &iwk[jwipc - 1], &wk[0]);
                    }
                  /* INTERPOLATES THE ZI VALUES.  (FOR MD=1,2,3) */
                  itpv = 0;
                  jig0mx = 0;
                  jig1mn = nxi0 * nyi0 + 1;
                  nngp = nt + 2 * nl;
                  for (jngp = 1; jngp <= nngp; ++jngp)
                    {
                      iti = jngp;
                      if (jngp > nt)
                        {
                          il1 = (jngp - nt + 1) / 2;
                          il2 = (jngp - nt + 2) / 2;
                          if (il2 > nl)
                            {
                              il2 = 1;
                            }
                          iti = il1 * (nt + nl) + il2;
                        }
                      jwngp = jwngp0 + jngp;
                      ngp0 = iwk[jwngp - 1];
                      if (ngp0 != 0)
                        {
                          jig0mn = jig0mx + 1;
                          jig0mx += ngp0;
                          for (jigp = jig0mn; jigp <= jig0mx; ++jigp)
                            {
                              jwigp = jwigp0 + jigp;
                              izi = iwk[jwigp - 1];
                              iyi = (izi - 1) / nxi0 + 1;
                              ixi = izi - nxi0 * (iyi - 1);
                              if (linear)
                                {
                                  idlcom(&xi[ixi - 1], &yi[iyi - 1], &zi[izi - 1], &iti, &xd[0], &yd[0], &zd[0], &nt,
                                         &iwk[jwipt - 1], &wk[0]);
                                }
                              else
                                {
                                  idptip(&xd[0], &yd[0], &zd[0], &nt, &iwk[jwipt - 1], &nl, &iwk[jwipl - 1], &wk[0],
                                         &iti, &xi[ixi - 1], &yi[iyi - 1], &zi[izi - 1], &itpv);
                                }
                              /* L30: */
                            }
                        }
                      jwngp = jwngp0 + 2 * nngp + 1 - jngp;
                      ngp1 = iwk[jwngp - 1];
                      if (ngp1 != 0)
                        {
                          jig1mx = jig1mn - 1;
                          jig1mn -= ngp1;
                          for (jigp = jig1mn; jigp <= jig1mx; ++jigp)
                            {
                              jwigp = jwigp0 + jigp;
                              izi = iwk[jwigp - 1];
                              iyi = (izi - 1) / nxi0 + 1;
                              ixi = izi - nxi0 * (iyi - 1);
                              if (linear)
                                {
                                  idlcom(&xi[ixi - 1], &yi[iyi - 1], &zi[izi - 1], &iti, &xd[0], &yd[0], &zd[0], &nt,
                                         &iwk[jwipt - 1], &wk[0]);
                                }
                              else
                                {
                                  idptip(&xd[0], &yd[0], &zd[0], &nt, &iwk[jwipt - 1], &nl, &iwk[jwipl - 1], &wk[0],
                                         &iti, &xi[ixi - 1], &yi[iyi - 1], &zi[izi - 1], &itpv);
                                }
                              /* L40: */
                            }
                        }
                      /* L20: */
                    }
                  return;
                }
            }
        }
    }
  /* ERROR EXIT */
L10:
  fprintf(stderr,
          " ***   IMPROPER INPUT PARAMETER VALUE(S)."
          "   MD =%4d   NCP =%6d   NDP = %6d   NXI =%6d   NYI =%6d\n",
          md0, ncp0, ndp0, nxi0, nyi0);
}
