program main c*********************************************************************72 c cc steinerberger_test() tests steinerberger(). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 29 March 2025 c c Author: c c John Burkardt c implicit none double precision, allocatable :: fx(:) character ( len = 255 ) header integer i integer j integer n integer, dimension ( 6 ) :: ntest = (/ 1, 5, 10, 25, 50, 100 /) integer, parameter :: nx = 5001 character ( len = 3 ) s3 double precision steinerberger_function double precision, allocatable :: x(:) call timestamp ( ) write ( *, '(a)' ) '' write ( *, '(a)' ) 'steinerberger_test():' write ( *, '(a)' ) ' Fortran77 version' write ( *, '(a)' ) ' Test steinerberger()' c c Plots. c write ( *, '(a)' ) '' write ( *, '(a)' ) ' Plot f(n,x) for several values of n' write ( *, '(a)' ) '' allocate ( x(1:nx) ) call r8vec_linspace ( nx, 0.0D+00, 1.0D+00, x ) allocate ( fx(1:nx) ) do i = 1, 6 n = ntest(i) do j = 1, nx fx(j) = steinerberger_function ( n, x(j) ) end do call i4_to_s_zero ( n, s3 ) header = 'steinerberger_' // s3 call gnuplot_fx ( nx, x, fx, trim ( header ) ) end do deallocate ( fx ) deallocate ( x ) c c Terminate. c write ( *, '(a)' ) '' write ( *, '(a)' ) 'steinerberger_test():' write ( *, '(a)' ) ' Normal end of execution.' call timestamp ( ) return end subroutine digit_to_ch ( digit, ch ) c*********************************************************************72 c cc digit_to_ch() returns the character representation of a decimal digit. c c Discussion: c c Instead of CHAR, we now use the ACHAR function, which c guarantees the ASCII collating sequence. c c Example: c c DIGIT CH c ----- --- c 0 '0' c 1 '1' c ... ... c 9 '9' c 17 '*' c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 04 September 2021 c c Author: c c John Burkardt c c Input: c c integer DIGIT, the digit value between 0 and 9. c c Output: c c character CH, the corresponding character. c implicit none character ch integer digit if ( 0 <= digit .and. digit <= 9 ) then ch = achar ( digit + 48 ) else ch = '*' end if 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. The code 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 26 October 2008 c c Author: c c John Burkardt c c Output: c c integer IUNIT, the free unit number. c implicit none integer i integer ios integer iunit logical lopen iunit = 0 do i = 1, 99 if ( i /= 5 .and. i /= 6 .and. i /= 9 ) then inquire ( unit = i, opened = lopen, iostat = ios ) if ( ios == 0 ) then if ( .not. lopen ) then iunit = i return end if end if end if end do return end subroutine gnuplot_fx ( n, x, y, header ) c*********************************************************************72 c cc gnuplot_fx() plots x, f(x) data. c c Discussion: c c Actually, we simply create two files for processing by gnuplot(). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 24 March 2025 c c Author: c c John Burkardt c implicit none integer n character ( len = 255 ) command_filename integer command_unit character ( len = 255 ) data_filename integer data_unit character ( len = * ) header integer i character ( len = 255 ) png_filename double precision x(n) double precision y(n) c c Create a graphics data file. c data_filename = header // '_data.txt' call get_unit ( data_unit ) open ( unit = data_unit, file = data_filename, & status = 'replace' ) do i = 1, n write ( data_unit, '(2g14.6)' ) x(i), y(i) end do close ( unit = data_unit ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' Created graphics data file "' & // trim ( data_filename ) // '".' png_filename = header // '.png' c c Create graphics command file. c call get_unit ( command_unit ) command_filename = header // '_commands.txt' 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 output "' & // trim ( png_filename ) // '"' write ( command_unit, '(a)' ) 'set xlabel "<--- X --->"' write ( command_unit, '(a)' ) 'set ylabel "<-- Y(X) -->"' write ( command_unit, '(a)' ) 'set title "' // header // '"' 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 command file "' & // trim ( command_filename ) // '".' return end subroutine i4_to_s_zero ( intval, s ) c*********************************************************************72 c cc i4_to_s_zero() converts an I4 to a string, with zero padding. c c Discussion: c c An I4 is an integer. c c Example: c c Assume that S is 6 characters long: c c INTVAL S c c 1 000001 c -1 -00001 c 0 000000 c 1952 001952 c 123456 123456 c 1234567 ****** <-- Not enough room! c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 04 August 1999 c c Author: c c John Burkardt c c Input: c c integer INTVAL, an integer to be converted. c c Output: c c character ( len = * ) S, the representation of the integer. c The integer will be right justified, and zero padded. c If there is not enough space, the string will be filled with stars. c implicit none character c integer i integer idig integer ihi integer ilo integer intval integer ipos integer ival character ( len = * ) s s = ' ' ilo = 1 ihi = len ( s ) if ( ihi <= 0 ) then return end if c c Make a copy of the integer. c ival = intval c c Handle the negative sign. c if ( ival < 0 ) then if ( ihi <= 1 ) then s(1:1) = '*' return end if ival = -ival s(1:1) = '-' ilo = 2 end if c c Working from right to left, strip off the digits of the integer c and place them into S(ILO:IHI). c ipos = ihi do while ( ival /= 0 .or. ipos == ihi ) idig = mod ( ival, 10 ) ival = ival / 10 if ( ipos < ilo ) then do i = 1, ihi s(i:i) = '*' end do return end if call digit_to_ch ( idig, c ) s(ipos:ipos) = c ipos = ipos - 1 end do c c Fill the empties with zeroes. c do i = ilo, ipos s(i:i) = '0' 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 == 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 timestamp ( ) c*********************************************************************72 c cc timestamp() prints the current YMDHMS date as a time stamp. c c Example: c c 31 May 2001 9:45:54.872 AM c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 15 August 2021 c c Author: c c John Burkardt c implicit none character ( len = 8 ) ampm integer d integer h integer m integer mm character ( len = 9 ), parameter, dimension(12) :: month = (/ & 'January ', 'February ', 'March ', 'April ', & 'May ', 'June ', 'July ', 'August ', & 'September', 'October ', 'November ', 'December ' /) integer n integer s integer values(8) integer y call date_and_time ( values = values ) y = values(1) m = values(2) d = values(3) h = values(5) n = values(6) s = values(7) mm = values(8) if ( h < 12 ) then ampm = 'AM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Noon' else ampm = 'PM' end if else h = h - 12 if ( h < 12 ) then ampm = 'PM' else if ( h == 12 ) then if ( n == 0 .and. s == 0 ) then ampm = 'Midnight' else ampm = 'AM' end if end if end if write ( *, & '(i2.2,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