subroutine aptafac (inum, nfactm, ifact, nfact, inumr, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTAFAC
c
c     call aptafac (inum, nfactm, ifact, nfact, inumr, nerr)
c
c     Version:  aptafac  Updated    2005 September 23 15:45.
c               aptafac  Originated 2005 September 23 15:45.
c
c     Authors:  Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  For the integer inum, find all factors ifact(n) > 1,
c               n = 1, nfact, with nfact limited to nfactm, and with each
c               factor used only once, except possibly the last factor.
c               If not all factors of inum are returned, because nfactm is
c               insufficient, then inumr, the remaining unfactored part of inum,
c               is returned with a value other than 1, with nerr = 3.
c
c               The method is slow, but avoids storing a large number of
c               numbers.  Each successive integer, 2, 3, 4, 5, 6, is tested as a
c               factor one time, and the result of dividing inum by each factor
c               used to limit the search to integers no larger than the square
c               root of that result.
c
c               Flag nerr indicates any input error or limited results.
c
c     Input:    inum, nfactm.
c
c     Output:   ifact, nfact, inumr, nerr.
c
c     Calls: (none) 
c
c     Glossary:
c
c     ifact        Output  Factor ifact(n) is the n'th smallest factor of inum,
c                            with each factor only used once, except possibly
c                            the last.
c                            If inum = 1, then ifact(1) = 1.
c                            Size at least nfactm.  Initially set to -999999999.
c
c     inum         Input   Any positive integer, for which all factors are to be
c                            found, up to a maximum of nfactm factors.
c
c     inumr        Output  Any remaining unfactored part of inum, when nfact
c                            is prevented from exceeding nfactm.  Normally 1.
c
c     nerr         Output  If not zero, indicates an error.
c                            1 if inum is not 1 or more.
c                            2 if nfactm is not positive.
c                            3 if more than nfactm factors exist.
c
c     nfact        Output  The number of factors found for integer inum.
c                            None may be used more than once.
c                            If nfactm are found, and more exist, nerr = 3.
c
c     nfactm       Input   The maximum allowed size of arrays ifact.
c                            On a machine with 64-bit integers, 18 is enough.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Declarations for arguments.

      integer ifact(1)                ! A factor of inum.
      integer inum                    ! Any positive integer.
      integer inumr                   ! Result of inum divided by all factors.
      integer nerr                    ! Indicates an error, if not zero.
      integer nfact                   ! How many factors of inum found.
      integer nfactm                  ! The maximum allowed value of nfact.

c.... Declarations for local variables.

      integer itest                   ! Integer to test as factor.
      integer itestm                  ! Maximum integer to test as factor.
      integer n                       ! Index in arrays ifact.

cbugc***DEBUG begins.
cbug 9901 format (/ 'aptafac finding factors of inum =',i20 /
cbug     &  '  but no more than',i6,' factors.' )
cbug      write ( 3, 9901) inum, nfactm
cbugc***DEBUG ends.

c.... Initialize.

      nerr   = 0
      nfact  = 0
      inumr  = inum

      if (nfactm .gt. 0) then
        do 100 n = 1, nfactm
          ifact(n) = -999999999
  100   continue
      endif

c.... Test for input errors.

      if (inum .lt. 1) then
        nerr = 1
        go to 210
      endif

      if (nfactm .le. 0) then
        nerr = 2
        go to 210
      endif

      if (inum .eq. 1) then
        nfact    = 1
        ifact(1) = 1
        go to 210
      endif

c.... Find maximum possible factor.

      itestm = sqrt (float (inumr))
cbugcbugc***DEBUG begins.
cbugcbug 9700 format ('DEBUG 0.  nfact,           itestm =',i3,21x,   i18)
cbugcbug      write ( 3, 9700) nfact, itestm
cbugcbugc***DEBUG ends.

c.... Test 2.

      itest = 2
      if (itest .gt. itestm) then   ! 2 is too high. 
        nfact        = nfact + 1
cbugcbugc***DEBUG begins.
cbugcbug 9801 format ('DEBUG A.  nfact,           itestm =',i3,21x,   i18)
cbugcbug      write ( 3, 9801) nfact, itestm
cbugcbugc***DEBUG ends.
        ifact(nfact) = inumr
        inumr        = 1
        go to 210
      endif                         ! 2 is too high.

      if (mod (inumr, itest) .eq. 0) then  ! Residual inumr is even.
        if (nfact .ge. nfactm) then
          nerr = 3
          go to 210
        endif
        nfact        = nfact + 1
cbugcbugc***DEBUG begins.
cbugcbug 9802 format ('DEBUG B.  nfact,           itestm =',i3,21x,   i18)
cbugcbug      write ( 3, 9802) nfact, itestm
cbugcbugc***DEBUG ends.
        ifact(nfact) = itest
        inumr        = inumr / itest
        if (inumr .eq. 1) go to 210
        itestm = sqrt (float (inumr))
cbugcbugc***DEBUG begins.
cbugcbug 9701 format ('DEBUG 1.  nfact,ifact,itestm =',i3,i18,i18)
cbugcbug      write ( 3, 9701) nfact, ifact(nfact), itestm
cbugcbugc***DEBUG ends.
      endif

      if (nfact .ge. nfactm) then
        nerr = 3
        go to 210
      endif

c.... Test each higher integer.

      itest = 3

  130 if (itest .gt. itestm) then
        nfact        = nfact + 1
cbugcbugc***DEBUG begins.
cbugcbug 9803 format ('DEBUG C.  nfact,           itestm =',i3,21x,   i18)
cbugcbug      write ( 3, 9803) nfact, itestm
cbugcbugc***DEBUG ends.
        ifact(nfact) = inumr
        inumr        = 1
        go to 210
      endif

      if (mod (inumr, itest) .eq. 0) then  ! Test next integer.

        nfact        = nfact + 1
cbugcbugc***DEBUG begins.
cbugcbug 9804 format ('DEBUG C.  nfact,           itestm =',i3,21x,   i18)
cbugcbug      write ( 3, 9804) nfact, itestm
cbugcbugc***DEBUG ends.
        ifact(nfact) = itest
        inumr        = inumr / itest
        if (inumr .eq. 1) go to 210
        itestm       = sqrt (float (inumr))
cbugcbugc***DEBUG begins.
cbugcbug 9703 format ('DEBUG 3.  nfact,ifact,itestm =',i3,i18,i18)
cbugcbug      write ( 3, 9703) nfact, ifact(nfact), itestm
cbugcbugc***DEBUG ends.

      endif                           ! Tested next odd integer.

      if (nfact .ge. nfactm) then
        nerr = 3
        go to 210
      endif

      itest = itest + 1
      go to 130
   
  210 continue
cbugc***DEBUG begins.
cbug 9902 format (/ 'aptafac found',i12,' factors.  nerr =',i3,'.' )
cbug 9903 format ('  n =',i3,'  ifact(n) =',i22)
cbug 9905 format ('  Unfactored residue =',i20)
cbug      write ( 3, 9902) nfact, nerr
cbug      if (nfact .gt. 0) then
cbug        write ( 3, 9903) (n, ifact(n), n = 1, nfact)
cbug      endif
cbug      if (nerr .eq. 3) then
cbug        write ( 3, 9905) inumr
cbug      endif
cbugc***DEBUG ends.
      return

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

UCRL-WEB-209832