program main c*********************************************************************72 c cc cosine_integral_test() tests cosine_integral(). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 11 August 2025 c c Author: c c John Burkardt c implicit none call timestamp ( ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'cosine_integral_test():' write ( *, '(a)' ) ' Fortran77 version' write ( *, '(a)' ) ' Test cosine_integral().' call ci_plot ( ) call ci_test ( ) c c Terminate. c write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'cosine_integral_test():' write ( *, '(a)' ) ' Normal end of execution.' write ( *, '(a)' ) ' ' call timestamp ( ) stop 0 end subroutine ci_plot ( ) c*********************************************************************72 c cc ci_plot() plots ci(x). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 11 August 2025 c c Author: c c John Burkardt c implicit none integer, parameter :: nplot = 101 double precision ci character ( len = 255 ) command_filename integer command_unit character ( len = 255 ) data_filename integer data_unit integer i character ( len = 255 ) output_filename character ( len = 100 ) prefix double precision xplot(nplot) double precision yplot(nplot) call r8vec_linspace ( nplot, -10.0D+00, +10.0D+00, xplot ) do i = 1, nplot yplot(i) = ci ( xplot(i) ) end do prefix = 'ci' c c Create the data file. c data_filename = trim ( prefix ) // '_data.txt' call get_unit ( data_unit ) open ( unit = data_unit, file = data_filename, & status = 'replace' ) do i = 1, nplot write ( data_unit, '(2x,g14.6,2x,g14.6)' ) xplot(i), yplot(i) end do close ( unit = data_unit ) write ( *, '(a)' ) '' write ( *, '(a)' ) ' Created graphics data file "' & // trim ( data_filename ) // '".' c c Plot the selected data. c command_filename = trim ( prefix ) // '_commands.txt' call get_unit ( command_unit ) open ( unit = command_unit, file = command_filename, & status = 'replace' ) write ( command_unit, '(a)' ) '# ' // trim ( command_filename ) write ( command_unit, '(a)' ) '#' write ( command_unit, '(a)' ) '# Usage:' write ( command_unit, '(a)' ) '# gnuplot < ' & // trim ( command_filename ) write ( command_unit, '(a)' ) '#' write ( command_unit, '(a)' ) 'set term png' write ( command_unit, '(a)' ) 'set nokey' output_filename = trim ( prefix ) // '_plot.png' write ( command_unit, '(a)' ) 'set output "' & // trim ( output_filename ) // '"' write ( command_unit, '(a)' ) 'set xlabel "<---X--->"' write ( command_unit, '(a)' ) 'set ylabel "<---Ci(X)--->"' write ( command_unit, '(a)' ) 'set title "Cosine integral Ci(x)"' write ( command_unit, '(a)' ) 'set grid' write ( command_unit, '(a)' ) 'set style data lines' write ( command_unit, '(a)' ) 'plot "' // trim ( data_filename ) & // '" using 1:2 lw 3 linecolor rgb "blue"' close ( unit = command_unit ) write ( *, '(a)' ) ' Created graphics command file "' & // trim ( command_filename ) // '".' return end subroutine get_unit ( iunit ) c*********************************************************************72 c cc get_unit() returns a free Fortran unit number. c c Discussion: c c A "free" Fortran unit number is a value between 1 and 99 which c is not currently associated with an I/O device. A free Fortran unit c number is needed in order to open a file with the OPEN command. c c If IUNIT = 0, then no free Fortran unit could be found, although c all 99 units were checked (except for units 5, 6 and 9, which c are commonly reserved for console I/O). c c Otherwise, IUNIT is a value between 1 and 99, representing a c free Fortran unit. Note that GET_UNIT assumes that units 5 and 6 c are special, and will never return those values. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 02 September 2013 c c Author: c c John Burkardt c c Output: c c integer IUNIT, the free unit number. c implicit none integer i integer iunit logical value iunit = 0 do i = 1, 99 if ( i .ne. 5 .and. i .ne. 6 .and. i .ne. 9 ) then inquire ( unit = i, opened = value, err = 10 ) if ( .not. value ) then iunit = i return end if end if 10 continue end do return end subroutine r8vec_linspace ( n, a, b, x ) c*********************************************************************72 c cc r8vec_linspace() creates a vector of linearly spaced values. c c Discussion: c c An R8VEC is a vector of R8's. c c 4 points evenly spaced between 0 and 12 will yield 0, 4, 8, 12. c c In other words, the interval is divided into N-1 even subintervals, c and the endpoints of intervals are used as the points. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 14 March 2011 c c Author: c c John Burkardt c c Input: c c integer N, the number of entries in the vector. c c double precision A, B, the first and last entries. c c Output: c c double precision X(N), a vector of linearly spaced data. c implicit none integer n double precision a double precision b integer i double precision x(n) if ( n .eq. 1 ) then x(1) = ( a + b ) / 2.0D+00 else do i = 1, n x(i) = ( dble ( n - i ) * a & + dble ( i - 1 ) * b ) & / dble ( n - 1 ) end do end if return end subroutine ci_test ( ) c*********************************************************************72 c cc ci_test() tests ci(). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 11 August 2025 c c Author: c c John Burkardt c implicit none double precision ci double precision fx1 double precision fx2 integer n_data double precision x write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'ci_test():' write ( *, '(a)' ) & ' ci() evaluates the cosine integral function.' write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' X SI(X)' write ( *, '(a)' ) ' ' n_data = 0 do call ci_values ( n_data, x, fx1 ) if ( n_data == 0 ) then exit end if fx2 = ci ( x ) write ( *, '(2x,g14.6,2x,g24.16,g24.16)' ) x, fx1, fx2 end do return end subroutine ci_values ( n_data, x, fx ) c*********************************************************************72 c cc ci_values() returns some values of the cosine integral function. c c Discussion: c c The cosine integral is defined by c c CI(X) = - integral ( X <= T < +oo ) ( cos ( T ) ) / T dT c c In Mathematica, the function can be evaluated by: c c CosIntegral(x) c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 21 March 2007 c c Author: c c John Burkardt c c Reference: c c Milton Abramowitz, Irene Stegun, c Handbook of Mathematical Functions, c National Bureau of Standards, 1964, c ISBN: 0-486-61272-4, c LC: QA47.A34. c c Stephen Wolfram, c The Mathematica Book, c Fourth Edition, c Cambridge University Press, 1999, c ISBN: 0-521-64314-7, c LC: QA76.95.W65. c c Input: c c integer N_DATA: the user should set N_DATA to 0 before the first call. c c Output: c c integer N_DATA: On each call, the routine increments N_DATA by 1, and c returns the corresponding data; when there is no more data, the c output value of N_DATA will be 0 again. c c double precision X, the argument of the function. c c double precision FX, the value of the function. c implicit none integer n_max parameter ( n_max = 16 ) double precision fx double precision fx_vec(n_max) integer n_data double precision x double precision x_vec(n_max) save fx_vec save x_vec data fx_vec / & -0.1777840788066129D+00, & -0.2227070695927976D-01, & 0.1005147070088978D+00, & 0.1982786159524672D+00, & 0.2760678304677729D+00, & 0.3374039229009681D+00, & 0.4204591828942405D+00, & 0.4620065850946773D+00, & 0.4717325169318778D+00, & 0.4568111294183369D+00, & 0.4229808287748650D+00, & 0.2858711963653835D+00, & 0.1196297860080003D+00, & -0.3212854851248112D-01, & -0.1409816978869304D+00, & -0.1934911221017388D+00 / data x_vec / & 0.5D+00, & 0.6D+00, & 0.7D+00, & 0.8D+00, & 0.9D+00, & 1.0D+00, & 1.2D+00, & 1.4D+00, & 1.6D+00, & 1.8D+00, & 2.0D+00, & 2.5D+00, & 3.0D+00, & 3.5D+00, & 4.0D+00, & 4.5D+00 / if ( n_data .lt. 0 ) then n_data = 0 end if n_data = n_data + 1 if ( n_max .lt. n_data ) then n_data = 0 x = 0.0D+00 fx = 0.0D+00 else x = x_vec(n_data) fx = fx_vec(n_data) end if return end subroutine timestamp ( ) c*********************************************************************72 c cc timestamp() prints the YMDHMS date as a timestamp. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 12 June 2014 c c Author: c c John Burkardt c implicit none character * ( 8 ) ampm integer d character * ( 8 ) date integer h integer m integer mm character * ( 9 ) month(12) integer n integer s character * ( 10 ) time integer y save month data month / & 'January ', 'February ', 'March ', 'April ', & 'May ', 'June ', 'July ', 'August ', & 'September', 'October ', 'November ', 'December ' / call date_and_time ( date, time ) read ( date, '(i4,i2,i2)' ) y, m, d read ( time, '(i2,i2,i2,1x,i3)' ) h, n, s, mm if ( h .lt. 12 ) then ampm = 'AM' else if ( h .eq. 12 ) then if ( n .eq. 0 .and. s .eq. 0 ) then ampm = 'Noon' else ampm = 'PM' end if else h = h - 12 if ( h .lt. 12 ) then ampm = 'PM' else if ( h .eq. 12 ) then if ( n .eq. 0 .and. s .eq. 0 ) then ampm = 'Midnight' else ampm = 'AM' end if end if end if write ( *, & '(i2,1x,a,1x,i4,2x,i2,a1,i2.2,a1,i2.2,a1,i3.3,1x,a)' ) & d, trim ( month(m) ), y, h, ':', n, ':', s, '.', mm, & trim ( ampm ) return end