      SUBROUTINE cumtnc(t,df,pnonc,cum,ccum)
C**********************************************************************
C
C     SUBROUTINE CUMTNC(T,DF,PNONC,CUM,CCUM)
C
C                 CUMulative Non-Central T-distribution
C
C
C                              Function
C
C
C     Computes the integral from -infinity to T of the non-central
C     t-density.
C
C
C                              Arguments
C
C
C     T --> Upper limit of integration of the non-central t-density.
C                                                  T is DOUBLE PRECISION
C
C     DF --> Degrees of freedom of the non-central t-distribution.
C                                                  DF is DOUBLE PRECISIO
C
C     PNONC --> Non-centrality parameter of the non-central t distibutio
C                                                  PNONC is DOUBLE PRECI
C
C     CUM <-- Cumulative t-distribution.
C                                                  CCUM is DOUBLE PRECIS
C
C     CCUM <-- Compliment of Cumulative t-distribution.
C                                                  CCUM is DOUBLE PRECIS
C
C
C                              Method
C
C     Upper tail    of  the  cumulative  noncentral t   using
C     formulae from page 532  of Johnson, Kotz,  Balakrishnan, Coninuous
C     Univariate Distributions, Vol 2, 2nd Edition.  Wiley (1995)
C
C     This implementation starts the calculation at i = lambda,
C     which is near the largest Di.  It then sums forward and backward.
C***********************************************************************
C     .. Parameters ..

      DOUBLE PRECISION one,zero,half,two,onep5
      PARAMETER (one=1.0d0,zero=0.0d0,half=0.5d0,two=2.0d0,onep5=1.5d0)
      DOUBLE PRECISION conv
      PARAMETER (conv=1.0d-7)
      DOUBLE PRECISION tiny
      PARAMETER (tiny=1.0d-10)
C     ..
C     .. Scalar Arguments ..
      DOUBLE PRECISION ccum,cum,df,pnonc,t
C     ..
C     .. Local Scalars ..
      DOUBLE PRECISION alghdf,b,bb,bbcent,bcent,cent,d,dcent,dpnonc,
     +                 dum1,dum2,e,ecent,halfdf,lambda,lnomx,lnx,omx,
     +                 pnonc2,s,scent,ss,sscent,t2,term,tt,twoi,x,
     +                 xi,xlnd,xlne
      INTEGER ierr
      LOGICAL qrevs
C     ..
C     .. External Functions ..
      DOUBLE PRECISION gamln
      EXTERNAL gamln
C     ..
C     .. External Subroutines ..
      EXTERNAL bratio,cumnor,cumt
C     ..
C     .. Intrinsic Functions ..
      INTRINSIC abs,exp,aint,log,max,min
C     ..

C     Case pnonc essentially zero

      IF (abs(pnonc).LE.tiny) THEN
          CALL cumt(t,df,cum,ccum)
          RETURN

      END IF

      qrevs = t .LT. zero
      IF (qrevs) THEN
          tt = -t
          dpnonc = -pnonc

      ELSE
          tt = t
          dpnonc = pnonc
      END IF

      pnonc2 = dpnonc*dpnonc
      t2 = tt*tt

      IF (abs(tt).LE.tiny) THEN
          CALL cumnor(-pnonc,cum,ccum)
          RETURN

      END IF

      lambda = half*pnonc2
      x = df/ (df+t2)
      omx = one - x

      lnx = log(x)
      lnomx = log(omx)

      halfdf = half*df
      alghdf = gamln(halfdf)

C     ******************** Case i = lambda

      cent = aint(lambda)

      IF (cent.LT.one) cent = one

C     Compute d=T(2i) in log space and offset by exp(-lambda)

      xlnd = cent*log(lambda) - gamln(cent+one) - lambda

      dcent = exp(xlnd)

C     Compute e=t(2i+1) in log space offset by exp(-lambda)

      xlne = (cent+half)*log(lambda) - gamln(cent+onep5) - lambda
      ecent = exp(xlne)

      IF (dpnonc.LT.zero) ecent = -ecent

C     Compute bcent=B(2*cent)

      CALL bratio(halfdf,cent+half,x,omx,bcent,dum1,ierr)

C     compute bbcent=B(2*cent+1)

      CALL bratio(halfdf,cent+one,x,omx,bbcent,dum2,ierr)

C     Case bcent and bbcent are essentially zero
C     Thus t is effectively infinite

      IF ((bcent+bbcent).LT.tiny) THEN
          IF (qrevs) THEN
              cum = zero
              ccum = one

          ELSE
              cum = one
              ccum = zero
          END IF

          RETURN

      END IF

C     Case bcent and bbcent are essentially one
C     Thus t is effectively zero

      IF ((dum1+dum2).LT.tiny) THEN
          CALL cumnor(-pnonc,cum,ccum)
          RETURN

      END IF

C     First term in ccum is D*B + E*BB

      ccum = dcent*bcent + ecent*bbcent

C     compute s(cent) = B(2*(cent+1)) - B(2*cent))

      scent = gamln(halfdf+cent+half) - gamln(cent+onep5) - alghdf +
     +        halfdf*lnx + (cent+half)*lnomx
      scent = exp(scent)

C     compute ss(cent) = B(2*cent+3) - B(2*cent+1)

      sscent = gamln(halfdf+cent+one) - gamln(cent+two) - alghdf +
     +         halfdf*lnx + (cent+one)*lnomx
      sscent = exp(sscent)

C     ******************** Sum Forward

      xi = cent + one
      twoi = two*xi

      d = dcent

      e = ecent

      b = bcent

      bb = bbcent

      s = scent

      ss = sscent

   10 b = b + s
      bb = bb + ss

      d = (lambda/xi)*d
      e = (lambda/ (xi+half))*e

      term = d*b + e*bb

      ccum = ccum + term

      s = s*omx* (df+twoi-one)/ (twoi+one)

      ss = ss*omx* (df+twoi)/ (twoi+two)

      xi = xi + one
      twoi = two*xi

      IF (abs(term).GT.conv*ccum) GO TO 10

C     ******************** Sum Backward

      xi = cent
      twoi = two*xi

      d = dcent

      e = ecent

      b = bcent

      bb = bbcent

      s = scent* (one+twoi)/ ((df+twoi-one)*omx)

      ss = sscent* (two+twoi)/ ((df+twoi)*omx)

   20 b = b - s
      bb = bb - ss

      d = d* (xi/lambda)

      e = e* ((xi+half)/lambda)

      term = d*b + e*bb

      ccum = ccum + term

      xi = xi - one

      IF (xi.LT.half) GO TO 30

      twoi = two*xi

      s = s* (one+twoi)/ ((df+twoi-one)*omx)

      ss = ss* (two+twoi)/ ((df+twoi)*omx)

      IF (abs(term).GT.conv*ccum) GO TO 20

   30 CONTINUE

      IF (qrevs) THEN
          cum = half*ccum
          ccum = one - cum

      ELSE
          ccum = half*ccum
          cum = one - ccum
      END IF

C     Due to roundoff error the answer may not lie between zero and one
C     Force it to do so

      cum = max(min(cum,one),zero)
      ccum = max(min(ccum,one),zero)

      RETURN

      END
