subroutine aptqupt (qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz,
     &                    tol, aqp, qpx, qpy, qpz, nqp, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTQUPT
c
c     call aptqupt (qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz,
c                   tol, aqp, qpx, qpy, qpz, nqp, nerr)
c
c     Version:  aptqupt  Updated    1994 November 9 12:20.
c               aptqupt  Originated 1994 November 9 12:20.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  For the quadric surface specified by the coordinates qc to qzz,
c               to find up to 6 points of the surface which are extreme points
c               in the x, y and z directions, up to 6 points which are
c               intercepts on the x, y and z axes, and up to 6 points which are
c               intercepts on the symmetry axes (x', y' and z') of the quadric
c               surface.
c 
c               The implicit equation of the quadric curve is:
c
c                 F(x,y,z) = qc + qx  * x     + qy  * y     +
c                                 qxy * x * y + qyz * y * z + qzx * z * x +
c                                 qxx * x**2  + qyy * y**2  + qzz * z**2  = 0  .
c
c               Results may be unpredictable if the coefficients of the quadric
c               surface differ by many orders of magnitude.
c
c     Method:   See subroutine aptqext for a description of the method of
c               finding extrema.
c
c               Any intercepts on the x, y and z axes or the symmetry axes are
c               solutions of the equations (in original or standard form):
c
c                 qc + qx * x + qxx * x**2 = 0
c                 qc + qy * y + qyy * y**2 = 0
c                 qc + qz * z + qzz * z**2 = 0
c
c     Input:    qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz, tol.
c
c     Output:   nqp, aqp, qpx, qpy, qpz, nerr.
c
c     Calls: aptaxis, aptmopv, aptqext, aptqrts, apttran 
c               
c
c     Glossary:
c
c     aqp       Output   Type of quadric surface point.  Array size must be at
c                          least 18.
c                          Minimum:  "Min x", "Min y" or "Min z".
c                          Maximum:  "Max x", "Max y" or "Max z".
c                          Aligned planes: "Const x", "Const y" or "Const z".
c                          Intersection of two planes, perpendicular to a major
c                          axis:
c                          "Inter x", "Inter y" or "Inter z".
c                          Saddle point:  "Saddle x", Saddle y" or "Saddle z".
c                          Singular isolated point:  "Point x", "Point y" or
c                          "Point z".
c                          X  axis intercept:  "Int x  1" or "Int x  2".
c                          Y  axis intercept:  "Int y  1" or "Int y  2".
c                          Z  axis intercept:  "Int z  1" or "Int z  2".
c                          X' axis intercept:  "Int x' 1" or "Int x' 2".
c                          Y' axis intercept:  "Int y' 1" or "Int y' 2".
c                          Z' axis intercept:  "Int z' 1" or "Int z' 2".
c                          If none, return "unknown".
c
c     qpx,y,z   Output   The x, y and z coordinates of an extreme point, a
c                          saddle point, or an intersection of two planes, for
c                          which the x, y or z coordinate is a maximum or a
c                          minimum, or an intercept on the x, y or z axis, or
c                          the x', y' or z' axis.  Array size must be at least
c                          18.  If none, return (-1.e99,-1.e99,-1.e99).
c
c     nerr      Output   Indicates an input error, if not zero:
c                          1 if all coefficients, except possible qc, are zero,
c                          or the quadric surface type is imaginary.
c
c     nqp       Output   Number of extreme and intercept points found.
c                          Never more than 18.
c
c     qc        In       Constant term in the equation of the quadric curve.
c
c     qx,qy,qz  In       Coefficients of x, y and z, respectively, in the
c                          equation of the quadric curve.
c
c     qxx       In       Coefficient of x**2 in the equation of the quadric
c                          curve.
c
c     qxy       In       Coefficient of x * y in the equation of the quadric
c                          curve.
c
c     qyy       In       Coefficient of y**2 in the equation of the quadric
c                          curve.
c
c     qyz       In       Coefficient of y * z in the equation of the quadric
c                          curve.
c
c     qzx       In       Coefficient of z * x in the equation of the quadric
c                          curve.
c
c     qzz       In       Coefficient of z**2 in the equation of the quadric
c                          curve.
c
c     tol       Input    Numerical tolerance limit.  With 64-bit floating
c                          point numbers, 1.e-5 to 1.e-11 is recommended.
c                          On 32-bit computers, recommend 1.e-6.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Dimensioned arguments.

      dimension aqp(1)                ! Type of quadric surface point.
      character*8 aqp                 ! Type of quadric surface point.
      dimension qpx(1)                ! Coordinate x of a point in quadric nq.
      dimension qpy(1)                ! Coordinate y of a point in quadric nq.
      dimension qpz(1)                ! Coordinate z of a point in quadric nq.

c.... Local variables.

      common /lqupt/ ex(6)            ! Coordinate x of extreme point.
      common /lqupt/ ey(6)            ! Coordinate y of extreme point.
      common /lqupt/ ez(6)            ! Coordinate z of extreme point.
      common /lqupt/ adir(6)          ! Type of extreme point.
      character*8 adir                ! Type of extreme point.
      common /lqupt/ rotq(3,3)        ! Standard form rotation operator.

c=======================================================================********
cbugc***DEBUG begins.
cbug 9901 format (/ 'aptqupt finding points on a quadric surface.' /
cbug     &  '  tol=',1pe13.5 )
cbug 9902 format (
cbug     &  '  qc=         ',1pe22.14 /
cbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbug      write ( 3, 9901) tol
cbug      write ( 3, 9902) qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz
cbugc***DEBUG ends.

c.... Initialize.

      nerr = 0
      nqp  = 0

      do 110 n = 1, 18
        aqp(n) = 'unknown'
        qpx(n) = -1.e99
        qpy(n) = -1.e99
        qpz(n) = -1.e99
  110 continue

c=======================================================================********

c.... Do the principal axis transformation on the quadric surface.

      ac  = qc
      ax  = qx
      ay  = qy
      az  = qz
      axy = qxy
      ayz = qyz
      azx = qzx
      axx = qxx
      ayy = qyy
      azz = qzz

      tolx = tol
      if (tolx .le. 0.0) tolx = 1.e-11

      call aptaxis (ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
     &              tol, cenx, ceny, cenz, rotq, ntype,
     &              nerra)

      if (ntype .gt. 16) then
        nerr = 1
        go to 210
      endif

      if (nerra .ne. 0) then
        nerr = 1
        go to 210
      endif

c.... See if the quadric surface is already in standard form.

      kstd = 0
      if ((rotq(1,1) .eq. 1.0)  .and.
     &    (rotq(2,2) .eq. 1.0)  .and.
     &    (rotq(3,3) .eq. 1.0)  .and.
     &    (cenx   .eq. 0.0)  .and.
     &    (ceny   .eq. 0.0)  .and.
     &    (cenz   .eq. 0.0)) then
        kstd = 1
      endif

c=======================================================================********

c.... Find any extreme points on the quadric surface.

      call aptqext (qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz,
     &              tol, ntyps, cenx, ceny, cenz, np, ex, ey, ez,
     &              adir, nerra)

      if (np .gt. 0) then
        do 120 nex = 1, np
          nqp      = nqp + 1
          aqp(nqp) = adir(nex)
          qpx(nqp) = ex(nex)
          qpy(nqp) = ey(nex)
          qpz(nqp) = ez(nex)
  120   continue
      endif

c=======================================================================********

c.... Find any intercepts of the original form on the x axis.

      call aptqrts (0, qxx, qx, qc, qq, tol,
     &              nroots, xint1, xint2, itrun)

      if (nroots .ge. 1) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int x  1'
        qpx(nqp) = xint1
        qpy(nqp) = 0.0
        qpz(nqp) = 0.0
      endif

      if (nroots .eq. 2) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int x  2'
        qpx(nqp) = xint2
        qpy(nqp) = 0.0
        qpz(nqp) = 0.0
      endif

c.... Find any intercepts of the original form on the y axis.

      call aptqrts (0, qyy, qy, qc, qq, tol,
     &              nroots, yint1, yint2, itrun)

      if (nroots .ge. 1) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int y  1'
        qpx(nqp) = 0.0
        qpy(nqp) = yint1
        qpz(nqp) = 0.0
      endif

      if (nroots .eq. 2) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int y  2'
        qpx(nqp) = 0.0
        qpy(nqp) = yint2
        qpz(nqp) = 0.0
      endif

c.... Find any intercepts of the original form on the z axis.

      call aptqrts (0, qzz, qz, qc, qq, tol,
     &              nroots, zint1, zint2, itrun)

      if (nroots .ge. 1) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int z  1'
        qpx(nqp) = 0.0
        qpy(nqp) = 0.0
        qpz(nqp) = zint1
      endif

      if (nroots .eq. 2) then
        nqp      = nqp + 1
        aqp(nqp) = 'Int z  2'
        qpx(nqp) = 0.0
        qpy(nqp) = 0.0
        qpz(nqp) = zint2
      endif

c=======================================================================********

c.... Skip stuff for standard form if quadric is already standard.

      if (kstd .eq. 1) go to 210

c=======================================================================********

c.... Find intercepts of standard form on x' axis, original coordinates.

      dx = -cenx
      dy = -ceny
      dz = -cenz

      call aptqrts (0, axx, 0., ac, qq, tol,
     &              nroots, xint1, xint2, itrun)

      if (nroots .ge. 1) then
        yr = 0.0
        zr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xint1, yr, zr, 1, tol,
     &                nerra)
        call apttran (dx, dy, dz, xint1, yr, zr, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int x'' 1'
        qpx(nqp) = xint1
        qpy(nqp) = yr
        qpz(nqp) = zr
      endif

      if (nroots .eq. 2) then
        yr = 0.0
        zr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xint2, yr, zr, 1, tol,
     &                nerr)
        call apttran (dx, dy, dz, xint2, yr, zr, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int x'' 2'
        qpx(nqp) = xint2
        qpy(nqp) = yr
        qpz(nqp) = zr
      endif

c=======================================================================********

c.... Find intercepts of standard form on y' axis, original coordinates.

      call aptqrts (0, ayy, 0., ac, qq, tol,
     &              nroots, yint1, yint2, itrun)

      if (nroots .ge. 1) then
        xr = 0.0
        zr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xr, yint1, zr, 1, tol,
     &                nerra)
        call apttran (dx, dy, dz, xr, yint1, zr, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int y'' 1'
        qpx(nqp) = xr
        qpy(nqp) = yint1
        qpz(nqp) = zr
      endif

      if (nroots .eq. 2) then
        xr = 0.0
        zr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xr, yint2, zr, 1, tol,
     &                nerra)
        call apttran (dx, dy, dz, xr, yint2, zr, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int y'' 2'
        qpx(nqp) = xr
        qpy(nqp) = yint2
        qpz(nqp) = zr
      endif

c=======================================================================********

c.... Find intercepts of standard form on z' axis, original coordinates.

      call aptqrts (0, azz, az, ac, qq, tol,
     &              nroots, zint1, zint2, itrun)

      if (nroots .ge. 1) then
        xr = 0.0
        yr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xr, yr, zint1, 1, tol,
     &                nerra)
        call apttran (dx, dy, dz, xr, yr, zint1, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int z'' 1'
        qpx(nqp) = xr
        qpy(nqp) = yr
        qpz(nqp) = zint1
      endif

      if (nroots .eq. 2) then
        xr = 0.0
        yr = 0.0
        call aptmopv (rotq, 1, 0., 0., 0., xr, yr, zint2, 1, tol,
     &                nerra)
        call apttran (dx, dy, dz, xr, yr, zint2, 1, tol, nerra)
        nqp      = nqp + 1
        aqp(nqp) = 'Int z'' 2'
        qpx(nqp) = xr
        qpy(nqp) = yr
        qpz(nqp) = zint2
      endif

c=======================================================================********

  210 continue 
cbugc***DEBUG begins.
cbug 9910 format (/ 'aptqupt results:  nqp=',i2,' nerr=',i2)
cbug 9912 format (a8,'  xyz=',1p3e22.14)
cbug      write ( 3, 9910) nqp, nerr
cbug      do 991 n = 1, nqp
cbug        write ( 3, 9912) aqp(n), qpx(n), qpy(n), qpz(n)
cbug  991 continue
cbugc***DEBUG ends.

      return

c.... End of subroutine aptqupt.      (+1 line)
      end

UCRL-WEB-209832