Prev: Caveat: Can One Dim Local Arrays Using Argument List Integers ??
Next: Spam removal - volunteer?
From: glen herrmannsfeldt on 21 Dec 2009 17:04 James Van Buskirk <not_valid(a)comcast.net> wrote: (snip) > I had this problem with recursive I/O when I wrote a code generator > and posted it to the web so people could test it. It seemed > illogical to me that f90 allowed the programmer to write recursive > code but that f95 permitted compilers to implement I/O, even > internal I/O, via fixed data structures that made all I/O operations > non-reentrant. It seems that way, but it really shouldn't be so much of a problem in most cases. I was thinking that the problem goes back to Fortran II, but even in Fortran 66 you can't have function calls in I/O statements. Probably the most common extension to Fortran 66 allows expressions in subscripts, instead of the restricted subscripts allowed by the standard. In that case, you could have function calls in subscripts, but not as I/O list elements. I believe, at least at the time, my favorite addition in Fortran 77 was allowing expressions in the I/O list of WRITE statements. So many temporary variables used to be needed. So, why didn't they fix this with Fortran 90? I would guess that there were already so many other things being added that it was decided that this wasn't really needed. > But if my code was going to be generally usable I had to modify my > code. What I did was to create functions that could compose strings > from numbers using specification functions to determine their LENs. > Then I could compose a line of output via concatenation of several > such strings (function results) and invoke a subroutine to print > out a line of output. Worked really well except that some f95 > compilers had problems with the specification functions or in > general with complicated specification expressions. Here is an > example adapted to your program: (snip) I would have thought it easier to remove function calls from I/O lists, and use temporary variables to store the value. Though complicated by not knowing the length in advance, and no non-advancing I/O. -- glen
From: Den7 on 21 Dec 2009 17:08 On Dec 21, 1:32 pm, "James Van Buskirk" <not_va...(a)comcast.net> wrote: > "Den7" <rrr7...(a)gmail.com> wrote in message > > news:7af7ef60-ae7a-4287-95fc-9e19c71ef671(a)a39g2000pre.googlegroups.com... > > > So because I have to ask exactly what i need, the program-maximum is > > (can i mask more?) > > integer foo > > external foo > > open(11,file='11.out') > > open(11,file='12.out') > > write(11,*) foo(12) > > end > > integer function foo(i) > > character*9 char_I > > write(char_i,'(i9)') i > > write(12,*,err=1000) char_i > > 1000 foo=i > > end > > I had this problem with recursive I/O when I wrote a code generator > and posted it to the web so people could test it. It seemed > illogical to me that f90 allowed the programmer to write recursive > code but that f95 permitted compilers to implement I/O, even > internal I/O, via fixed data structures that made all I/O operations > non-reentrant. > > But if my code was going to be generally usable I had to modify my > code. What I did was to create functions that could compose strings > from numbers using specification functions to determine their LENs. > Then I could compose a line of output via concatenation of several > such strings (function results) and invoke a subroutine to print > out a line of output. Worked really well except that some f95 > compilers had problems with the specification functions or in > general with complicated specification expressions. Here is an > example adapted to your program: > > C:\gfortran\clf\recursive_io>type recursive_io.f90 > module stuff > implicit none > contains > subroutine write_unit(iunit,x) > integer, intent(in) :: iunit > character(*), intent(in) :: x > > write(iunit,'(a)') x > end subroutine write_unit > function compose_i4(x) > integer, intent(in) :: x > character(compose_i4_len(x)) compose_i4 > > write(compose_i4,*) x > end function compose_i4 > pure function compose_i4_len(x) > integer compose_i4_len > integer, intent(in) :: x > character(range(x)+3) temp > > write(temp,*) x > compose_i4_len = len_trim(temp) > end function compose_i4_len > end module stuff > > program test > use stuff > implicit none > integer foo > external foo > > open(11,file='11.out') > ! open(11,file='12.out') ! BUG! > open(12,file='12.out') > ! write(11,*) foo(12) > call write_unit(11,compose_i4(foo(12))) > end program test > > integer function foo(i) > implicit none > integer i > character*9 char_I > write(char_i,'(i9)') i > write(12,*,err=1000) char_i > 1000 foo=i > end function foo > > C:\gfortran\clf\recursive_io>gfortran -Wall recursive_io.f90 -orecursive_io > > C:\gfortran\clf\recursive_io>recursive_io > > C:\gfortran\clf\recursive_io>type 11.out > 12 > > C:\gfortran\clf\recursive_io>type 12.out > 12 > > For a more complex example, consider the usage of subroutine WX > inhttp://home.comcast.net/~kmbtib/conv2c.f90. > > -- > write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & > 6.0134700243160014d-154/),(/'x'/)); end Thanks for the example. Just report immediate error without looking inside to fix that : "attempt to write past end of internal file"
From: Den7 on 21 Dec 2009 17:25 On Dec 21, 1:32 pm, "James Van Buskirk" <not_va...(a)comcast.net> wrote: > "Den7" <rrr7...(a)gmail.com> wrote in message > > news:7af7ef60-ae7a-4287-95fc-9e19c71ef671(a)a39g2000pre.googlegroups.com... > > > So because I have to ask exactly what i need, the program-maximum is > > (can i mask more?) > > integer foo > > external foo > > open(11,file='11.out') > > open(11,file='12.out') > > write(11,*) foo(12) > > end > > integer function foo(i) > > character*9 char_I > > write(char_i,'(i9)') i > > write(12,*,err=1000) char_i > > 1000 foo=i > > end > > I had this problem with recursive I/O when I wrote a code generator > and posted it to the web so people could test it. It seemed > illogical to me that f90 allowed the programmer to write recursive > code but that f95 permitted compilers to implement I/O, even > internal I/O, via fixed data structures that made all I/O operations > non-reentrant. > > But if my code was going to be generally usable I had to modify my > code. What I did was to create functions that could compose strings > from numbers using specification functions to determine their LENs. > Then I could compose a line of output via concatenation of several > such strings (function results) and invoke a subroutine to print > out a line of output. Worked really well except that some f95 > compilers had problems with the specification functions or in > general with complicated specification expressions. Here is an > example adapted to your program: > > C:\gfortran\clf\recursive_io>type recursive_io.f90 > module stuff > implicit none > contains > subroutine write_unit(iunit,x) > integer, intent(in) :: iunit > character(*), intent(in) :: x > > write(iunit,'(a)') x > end subroutine write_unit > function compose_i4(x) > integer, intent(in) :: x > character(compose_i4_len(x)) compose_i4 > > write(compose_i4,*) x > end function compose_i4 > pure function compose_i4_len(x) > integer compose_i4_len > integer, intent(in) :: x > character(range(x)+3) temp > > write(temp,*) x > compose_i4_len = len_trim(temp) > end function compose_i4_len > end module stuff > > program test > use stuff > implicit none > integer foo > external foo > > open(11,file='11.out') > ! open(11,file='12.out') ! BUG! > open(12,file='12.out') > ! write(11,*) foo(12) > call write_unit(11,compose_i4(foo(12))) > end program test > > integer function foo(i) > implicit none > integer i > character*9 char_I > write(char_i,'(i9)') i > write(12,*,err=1000) char_i > 1000 foo=i > end function foo > > C:\gfortran\clf\recursive_io>gfortran -Wall recursive_io.f90 -orecursive_io > > C:\gfortran\clf\recursive_io>recursive_io > > C:\gfortran\clf\recursive_io>type 11.out > 12 > > C:\gfortran\clf\recursive_io>type 12.out > 12 > > For a more complex example, consider the usage of subroutine WX > inhttp://home.comcast.net/~kmbtib/conv2c.f90. > > -- > write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & > 6.0134700243160014d-154/),(/'x'/)); end Thanks for the example. Just report immediate error without looking inside to fix that : "attempt to write past end of internal file" I did not get though your idea as soon as i see killing it write(iunit,'(a)') x This compiler does not allow recursive I/O was it real I/O or internal file I/O
From: robin on 21 Dec 2009 18:46 Den7 wrote in message ... >Please look at this code, why this code is forbidden (in my compiler >at least) ? And what compiler is that? F77? > > integer foo > external foo > > open(11,file='11.out') > open(12,file='12.out') > write(11,*) foo(12) > end > > integer function foo(i) > write(12,*) i >1000 foo=i > end function foo > >Even if i write into character variable (so called internal write or >something like that) i have the same problem. >Even more, if i make > > write(12,*,err=1000) i > >i still have the crash. How about your compiler? > >The error is "The function called from within an I/O statement has >itself performed an I/O". That's because it is recursive I/O. >It sounds to me as silly as this: "The function called from within >multiplication has itself performed a multiplication", but there could >be nasty reasons for forbidding this kind of I/Os requiring >multithreading or so. It requires recursion, not multithreading. Why not change FOO to a subroutine? Then you don't have that problem.
From: Den7 on 21 Dec 2009 19:02
On Dec 21, 3:46 pm, "robin" <robi...(a)bigpond.com> wrote: > Den7 wrote in message ... > >Please look at this code, why this code is forbidden (in my compiler > >at least) ? > > And what compiler is that? F77? > > > > > > > > > integer foo > > external foo > > > open(11,file='11.out') > > open(12,file='12.out') > > write(11,*) foo(12) > > end > > > integer function foo(i) > > write(12,*) i > >1000 foo=i > > end function foo > > >Even if i write into character variable (so called internal write or > >something like that) i have the same problem. > >Even more, if i make > > > write(12,*,err=1000) i > > >i still have the crash. How about your compiler? > > >The error is "The function called from within an I/O statement has > >itself performed an I/O". > > That's because it is recursive I/O. > > >It sounds to me as silly as this: "The function called from within > >multiplication has itself performed a multiplication", but there could > >be nasty reasons for forbidding this kind of I/Os requiring > >multithreading or so. > > It requires recursion, not multithreading. > > Why not change FOO to a subroutine? > Then you don't have that problem. in mulththreading we have special lock mechanism which allows I/O even on the same unit, if you lock it until it finishes its work, then unlock. Another I/O will then safely come so two overlapping in time I/Os will not conflict. That is one more option i reluctantly pursue now... |