!! Barlow and Barnett, Computing for Scientists 1998
!! page 54                  C++ and Fortran 90

! simple example of use of loops and branches

! Calculates log(n!), using different methods.

PROGRAM log_factorial

  IMPLICIT NONE
  INTEGER :: i , n , int_prod
  REAL    :: xn , r , r2 , real_prod , PI
  REAL    :: fac1 , fac2 , fac3 , logfac

  PI = 4.d0*ATAN(1.0d0)
     
  PRINT * , ' Integer factorial 1-10000'
  READ  * , n; IF (n < 1) STOP ' n < 1 '
  xn = REAL(n); r = 1.0/xn; r2 = r*r

  IF (n < 13) THEN
     int_prod = 1
     DO i = 1 , n
        int_prod = int_prod * i
     ENDDO
     logfac =  log(REAL(int_prod))

  ELSEIF (n < 35) THEN
     real_prod = 1.0
     DO i = 1 , n
        real_prod = real_prod*REAL(i)
     ENDDO
     logfac =  log(real_prod)

  ELSE
     logfac = 0.0
     DO i = 1 , n
        logfac =  logfac +  log(REAL(i))
     ENDDO
  ENDIF

  fac1 = xn*log(xn) - xn
  fac2 = fac1 + 0.5*(log(2.0*PI*xn))
  fac3 = fac2 + (r/12.) * (1. - r2*(1./30.&
         - r2*(1./105. - r2*(1./140. - r2/99.))))
  PRINT * , ' n ,  log n! , & approximations'
  PRINT * , n ,  logfac , fac1 , fac2 , fac3

END PROGRAM log_factorial
