• Variable values after READ encounters errors

    From Beliavsky@21:1/5 to All on Sat Mar 26 05:06:39 2022
    In section 10.7 of Metcalf/Reid/Cohen (2018), they write, "If an error or end-of-file condition occurs on input, the statement terminates and all list items and any implied-do variables become undefined."

    Although gfortran, g95, ifort, and flang all say that i is 42 and j is 8 at the end of the following code, I believe the Fortran standard does not mandate this. Correct?

    program main
    implicit none
    character (len=100) :: text
    integer :: i,j,ierr
    text = "42 abc"
    i = 7
    j = 8
    read (text,*,iostat=ierr) i,j
    print*,"ierr, i, j =",ierr,i,j
    end program main

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Thomas Koenig on Sat Mar 26 06:42:23 2022
    On Saturday, March 26, 2022 at 9:26:09 AM UTC-4, Thomas Koenig wrote:
    Beliavsky <beli...@aol.com> schrieb:
    In section 10.7 of Metcalf/Reid/Cohen (2018), they write, "If
    an error or end-of-file condition occurs on input, the statement
    terminates and all list items and any implied-do variables become undefined."
    Unsurprisingly, the authors are right. And I quote:

    12.11.2 Error conditions and the ERR= specifier

    [...]

    If an error condition occurs during execution of an input/output
    statement that contains either an ERR= specifier or an IOSTAT=
    specifier then:

    [...]

    (2) if the statement is a data transfer statement or the error
    condition occurs during a wait operation, all do-variables in the
    statement that initiated the transfer become undefined;

    [...]

    (6) if the statement is a data transfer statement or the error
    condition occurs during a wait operation, all do-variables in the
    statement that initiated the transfer become undefined;
    Although gfortran, g95, ifort, and flang all say that i is 42
    and j is 8 at the end of the following code, I believe the Fortran
    standard does not mandate this. Correct?
    Correct. There is a fine difference between "works when tested" and "advertised as working in extension to the standard". Any compiler
    might have chosen to document this behavior (gfortran didn't), then
    it would be possible to rely on it for that particular compiler,
    but it would be non-portable. As is, the behavior might change
    with a new version, a different optimization option, or (somewhat
    unlikely) the phase of the moon.

    Since all the compilers I have tested update the variables that can be read
    and preserve the old values of the variable that cannot be read, and since this behavior may be what the user wants, would it make sense to add a PRESERVE specifier to the READ statement? With PRESERVE=.TRUE. the current behavior would be mandated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Beliavsky on Sat Mar 26 13:26:06 2022
    Beliavsky <beliavsky@aol.com> schrieb:

    In section 10.7 of Metcalf/Reid/Cohen (2018), they write, "If
    an error or end-of-file condition occurs on input, the statement
    terminates and all list items and any implied-do variables become
    undefined."

    Unsurprisingly, the authors are right. And I quote:

    12.11.2 Error conditions and the ERR= specifier

    [...]

    If an error condition occurs during execution of an input/output
    statement that contains either an ERR= specifier or an IOSTAT=
    specifier then:

    [...]

    (2) if the statement is a data transfer statement or the error
    condition occurs during a wait operation, all do-variables in the
    statement that initiated the transfer become undefined;

    [...]

    (6) if the statement is a data transfer statement or the error
    condition occurs during a wait operation, all do-variables in the
    statement that initiated the transfer become undefined;

    Although gfortran, g95, ifort, and flang all say that i is 42
    and j is 8 at the end of the following code, I believe the Fortran
    standard does not mandate this. Correct?

    Correct. There is a fine difference between "works when tested" and "advertised as working in extension to the standard". Any compiler
    might have chosen to document this behavior (gfortran didn't), then
    it would be possible to rely on it for that particular compiler,
    but it would be non-portable. As is, the behavior might change
    with a new version, a different optimization option, or (somewhat
    unlikely) the phase of the moon.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Beliavsky on Sat Mar 26 19:17:23 2022
    Beliavsky <beliavsky@aol.com> schrieb:

    Since all the compilers I have tested update the variables that can be read and preserve the old values of the variable that cannot be read, and since this
    behavior may be what the user wants, would it make sense to add a PRESERVE specifier to the READ statement? With PRESERVE=.TRUE. the current behavior would be mandated.

    The tradition of Fortran is to use strings for I/O, such as
    ADVANCE="NO". Of course, your proposal could be amended for that.

    It would also be necessary to specify what happens for asynchronous
    I/O.

    If a compiler has a different way of doing I/O that makes this hard,
    such a provision would force that compiler to a) change that method,
    and b) to make it selectable at run-time - a user might specify
    a string (or that would have to be disallowed.

    If a user wants that effect, it is probably better to use
    individual I/O statements. Stream I/O and non-advancing I/O
    should offer enough possibilities to do this. Or, it is also
    possible to specify something like

    read (unit,fmt,iostat=ios) tmp
    if (ios == 0) a = tmp

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Thomas Koenig on Sat Mar 26 12:42:23 2022
    On Saturday, March 26, 2022 at 3:17:27 PM UTC-4, Thomas Koenig wrote:
    Beliavsky <beli...@aol.com> schrieb:
    Since all the compilers I have tested update the variables that can be read and preserve the old values of the variable that cannot be read, and since this
    behavior may be what the user wants, would it make sense to add a PRESERVE specifier to the READ statement? With PRESERVE=.TRUE. the current behavior would be mandated.
    The tradition of Fortran is to use strings for I/O, such as
    ADVANCE="NO". Of course, your proposal could be amended for that.

    It would also be necessary to specify what happens for asynchronous
    I/O.

    If a compiler has a different way of doing I/O that makes this hard,
    such a provision would force that compiler to a) change that method,
    and b) to make it selectable at run-time - a user might specify
    a string (or that would have to be disallowed.

    If a user wants that effect, it is probably better to use
    individual I/O statements. Stream I/O and non-advancing I/O
    should offer enough possibilities to do this. Or, it is also
    possible to specify something like

    read (unit,fmt,iostat=ios) tmp
    if (ios == 0) a = tmp

    Thanks for your comments and code. The safe way of writing my original code is

    program main
    implicit none
    character (len=100) :: text
    integer :: i,j,itmp,jtmp,ierr
    text = "42 abc"
    i = 7
    j = 8
    ! try to read two integers
    read (text,*,iostat=ierr) itmp,jtmp
    if (ierr == 0) then
    i = itmp
    j = jtmp
    else ! try to read one integer
    read (text,*,iostat=ierr) itmp
    if (ierr == 0) i = itmp
    end if
    print*,"i, j =",i,j
    end program main
    ! output with gfortran, g95, ifort, and flang
    ! i, j = 42 8

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Thomas Koenig on Sat Mar 26 18:25:09 2022
    On Saturday, March 26, 2022 at 12:17:27 PM UTC-7, Thomas Koenig wrote:
    Beliavsky <beli...@aol.com> schrieb:

    (snip)

    I first learned about this almost 40 years ago on VAX. I wanted to use
    the implied-DO variable to find out how many were read before END=.
    I was close to sending a bug report, though I had never seen an actual
    copy of the standard. It might be that the DEC manual documented
    this, though.

    The tradition of Fortran is to use strings for I/O, such as
    ADVANCE="NO". Of course, your proposal could be amended for that.

    It would also be necessary to specify what happens for asynchronous
    I/O.

    If a compiler has a different way of doing I/O that makes this hard,
    such a provision would force that compiler to a) change that method,
    and b) to make it selectable at run-time - a user might specify
    a string (or that would have to be disallowed.

    C's scanf() family has no error modes.

    It is defined such that successfully read values are guaranteed to be
    stored, and ones that haven't been reached are guaranteed unchanged.
    (I am not so sure about asynchronous I/O, but I don't think scanf()
    does that.)

    Note that there are no conversion errors in C. Formatted I/O for
    numeric descriptors ends without error when a character that
    can't be used is found, and that character is left for the next
    I/O operation to read.

    scanf() returns the number of successful read items,
    including the number read before EOF.

    If a user wants that effect, it is probably better to use
    individual I/O statements. Stream I/O and non-advancing I/O
    should offer enough possibilities to do this. Or, it is also
    possible to specify something like

    Since Fortran stream I/O was designed based on C, it would seem
    reasonable for it to follow C's rules, when possible.


    read (unit,fmt,iostat=ios) tmp
    if (ios == 0) a = tmp

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Beliavsky on Sat Mar 26 19:27:50 2022
    On Saturday, March 26, 2022 at 11:06:41 PM UTC+11, Beliavsky wrote:
    In section 10.7 of Metcalf/Reid/Cohen (2018), they write, "If an error or end-of-file condition occurs on input, the statement terminates and all list items and any implied-do variables become undefined."

    Although gfortran, g95, ifort, and flang all say that i is 42 and j is 8 at the end of the following code, I believe the Fortran standard does not mandate this. Correct?
    .
    Undefined means "undefined".
    It doesn't matter what values the variables have, they are still undefined
    and you cannot use them.
    .
    program main
    implicit none
    character (len=100) :: text
    integer :: i,j,ierr
    text = "42 abc"
    i = 7
    j = 8
    read (text,*,iostat=ierr) i,j
    print*,"ierr, i, j =",ierr,i,j
    end program main

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Beliavsky on Sun Mar 27 10:11:59 2022
    On Saturday, March 26, 2022 at 9:42:25 AM UTC-4, Beliavsky wrote:
    Since all the compilers I have tested update the variables that can be read and preserve the old values of the variable that cannot be read, and since this
    behavior may be what the user wants, would it make sense to add a PRESERVE specifier to the READ statement? With PRESERVE=.TRUE. the current behavior would be mandated.

    A further suggestion. When reading an array from a string, the returned IOSTAT tells you whether or not the entire array could be read, but it would be nice to know
    how many of the array elements could be read. An NREAD specifier returning an integer could be used for this. Since a READ statement may have multiple scalar and array items, the NREAD would correspond to the last item in the list. If it is a
    scalar, NREAD would be 1 if the scalar were read, otherwise 0. As demonstrated at
    https://github.com/Beliavsky/FortranTip/blob/main/iomsg.f90 , IOMSG from gfortran
    currently gives an informative message saying which item in a list could not be read,
    but the IOMSG from Intel Fortran does not provide this information.

    Fortran 202x will have SPLIT intrinsics. One can split lines into strings and read
    individual items from them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Beliavsky on Mon Mar 28 05:43:47 2022
    On Monday, March 28, 2022 at 4:12:01 AM UTC+11, Beliavsky wrote:
    On Saturday, March 26, 2022 at 9:42:25 AM UTC-4, Beliavsky wrote:
    Since all the compilers I have tested update the variables that can be read and preserve the old values of the variable that cannot be read, and since this
    behavior may be what the user wants, would it make sense to add a PRESERVE specifier to the READ statement? With PRESERVE=.TRUE. the current behavior would be mandated.
    A further suggestion. When reading an array from a string, the returned IOSTAT
    tells you whether or not the entire array could be read, but it would be nice to know
    how many of the array elements could be read. An NREAD specifier returning an integer could be used for this. Since a READ statement may have multiple scalar
    and array items, the NREAD would correspond to the last item in the list. If it is a
    scalar, NREAD would be 1 if the scalar were read, otherwise 0. As demonstrated at
    https://github.com/Beliavsky/FortranTip/blob/main/iomsg.f90 , IOMSG from gfortran
    currently gives an informative message saying which item in a list could not be read,
    but the IOMSG from Intel Fortran does not provide this information.

    Fortran 202x will have SPLIT intrinsics. One can split lines into strings and read
    individual items from them.
    .
    I can't believe that this discussion is still raging after 50 years.
    .
    If you want these facilities, use PL/I. which stores those values that
    were read in, and leaves unchanged those variables for which
    a value could not be read in on account of some error or whatever.
    .
    PL/I even provides a variable (COUNT) that tells you the
    number of values that were successfully read and stored.
    .
    We have been using these PL/I facilities for 55 years.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Robin Vowels on Mon Mar 28 06:50:50 2022
    On Monday, March 28, 2022 at 8:43:49 AM UTC-4, Robin Vowels wrote:

    If you want these facilities, use PL/I. which stores those values that
    were read in, and leaves unchanged those variables for which
    a value could not be read in on account of some error or whatever.
    .
    PL/I even provides a variable (COUNT) that tells you the
    number of values that were successfully read and stored.
    .
    We have been using these PL/I facilities for 55 years.

    Robin,
    I think programming languages sometimes become so unpopular and
    unsupported that they are not viable, regardless of their intrinsic merits. Some say this about Fortran, but I hope they are wrong. I think it is true
    of PL/1. You have been educating us about Pl/I for years (decades?. More
    than one millennium?) Besides the Wikipedia article, what are the best
    online resources in your opinion? Maybe reading them would give
    Fortranners some ideas.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Beliavsky on Mon Mar 28 12:31:12 2022
    On Monday, March 28, 2022 at 6:50:52 AM UTC-7, Beliavsky wrote:

    (snip)

    We have been using these PL/I facilities for 55 years.

    Possibly with a 55 year old compiler.


    Robin,
    I think programming languages sometimes become so unpopular and
    unsupported that they are not viable, regardless of their intrinsic merits. Some say this about Fortran, but I hope they are wrong. I think it is true
    of PL/1. You have been educating us about Pl/I for years (decades?. More
    than one millennium?) Besides the Wikipedia article, what are the best
    online resources in your opinion? Maybe reading them would give
    Fortranners some ideas.

    I was doing both Fortran and PL/I programming in 9th grade.

    My Algebra I book actually had a PL/I chapter, but we conveniently
    skipped over it. That was Fortran IV days, and I found PL/I much
    more fun to program in.

    There are actual stories from those designing PL/I. Among others,
    and I suspect unlike many programming languages, PL/I (or NPL)
    was designed before the first compiler was started.

    (For those interested, there is what Knuth calls Fortran 0, that is,
    the language as it was thought up before the first compiler.)

    In any case, when they were first working on PL/I, they thought about
    making it more compatible with (the then current) Fortran, but decided
    that in the time they had (less than a year) that was not possible.

    One result of designing before implementation, is that come features
    turned out harder to implement than they might have thought.
    (And especially considering the smaller and slower computers
    of the time.) Many original PL/I features have now made it into
    Fortran, close to 60 years later. It is also interesting to see the
    ones that haven't.

    For one, PL/I had generic intrinsic functions from the beginning,
    and still more generic than Fortran. You can, for example, call
    SQRT with an integer (that is, fixed point) argument. Since PL/I
    allows fixed point types with the radix point other than just to the
    right of the LSD, that makes sense. (In many cases, values are
    converted to double precision floating point, and that is used
    for the actual function call.) And yet Fortran still doesn't do that.

    (PL/I will even let you call SQRT with a CHAR argument, and do
    the conversion for you, if the value looks like a number.)

    Sometimes it looks to me that when features are added to Fortran,
    they try to make it as hard as possible for users to use them.
    Complicated rules are added, so that both compiler writers
    and programmers have a hard time figuring them out.

    It looks to me like PL/I tends to have simpler rules, though
    sometimes harder for compiler writers.

    But yes, there aren't enough PL/I users to get compilers writers
    interested, and not enough compilers to get users interested.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gary Scott@21:1/5 to All on Mon Mar 28 16:46:01 2022
    On 3/28/2022 2:31 PM, gah4 wrote:
    On Monday, March 28, 2022 at 6:50:52 AM UTC-7, Beliavsky wrote:

    (snip)

    We have been using these PL/I facilities for 55 years.

    Possibly with a 55 year old compiler.


    Robin,
    I think programming languages sometimes become so unpopular and
    unsupported that they are not viable, regardless of their intrinsic merits. >> Some say this about Fortran, but I hope they are wrong. I think it is true >> of PL/1. You have been educating us about Pl/I for years (decades?. More
    than one millennium?) Besides the Wikipedia article, what are the best
    online resources in your opinion? Maybe reading them would give
    Fortranners some ideas.

    I was doing both Fortran and PL/I programming in 9th grade.

    My Algebra I book actually had a PL/I chapter, but we conveniently
    skipped over it. That was Fortran IV days, and I found PL/I much
    more fun to program in.

    There are actual stories from those designing PL/I. Among others,
    and I suspect unlike many programming languages, PL/I (or NPL)
    was designed before the first compiler was started.

    (For those interested, there is what Knuth calls Fortran 0, that is,
    the language as it was thought up before the first compiler.)

    In any case, when they were first working on PL/I, they thought about
    making it more compatible with (the then current) Fortran, but decided
    that in the time they had (less than a year) that was not possible.

    One result of designing before implementation, is that come features
    turned out harder to implement than they might have thought.
    (And especially considering the smaller and slower computers
    of the time.) Many original PL/I features have now made it into
    Fortran, close to 60 years later. It is also interesting to see the
    ones that haven't.

    For one, PL/I had generic intrinsic functions from the beginning,
    and still more generic than Fortran. You can, for example, call
    SQRT with an integer (that is, fixed point) argument. Since PL/I
    allows fixed point types with the radix point other than just to the
    right of the LSD, that makes sense. (In many cases, values are
    converted to double precision floating point, and that is used
    for the actual function call.) And yet Fortran still doesn't do that.

    (PL/I will even let you call SQRT with a CHAR argument, and do
    the conversion for you, if the value looks like a number.)

    Sometimes it looks to me that when features are added to Fortran,
    they try to make it as hard as possible for users to use them.
    Complicated rules are added, so that both compiler writers
    and programmers have a hard time figuring them out.

    It looks to me like PL/I tends to have simpler rules, though
    sometimes harder for compiler writers.

    But yes, there aren't enough PL/I users to get compilers writers
    interested, and not enough compilers to get users interested.







    Some of those "features" of PL/I do not encourage the most efficient
    code. Fortran in some ways forces you to think in ways that encourage execution efficiency.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Gary Scott on Mon Mar 28 15:32:10 2022
    On Monday, March 28, 2022 at 2:46:07 PM UTC-7, Gary Scott wrote:

    (snip)

    Some of those "features" of PL/I do not encourage the most efficient
    code. Fortran in some ways forces you to think in ways that encourage execution efficiency.

    I suppose so.

    Well, I suspect that for any language, there are not so obvious ways to
    do things slow, and fast.

    A forever favorite for Fortran, at least since the days of virtual memory
    and cache, is using arrays in the wrong order.

    But often enough, code efficiency is not the first thing you should
    be thinking about. Getting the right answer is more important!

    OK, one funny thing. Fortran array expressions are defined such that
    the whole right hand side is evaluated before the left side is changed.
    (Not necessarily the most efficient way.) PL/I defines array expressions element by element, so if you do:

    X = X + X(10);

    the changed X(10) is used in later assignments.

    Either one could have left it undefined, such that it is up to the user
    to avoid the problem. PL/I compilers used to be good at warning you
    about temporary arrays that might be needed. More of a problem
    for space efficiency than time efficiency, but both can be important.

    It is hard to say that either one encourages efficient code, though.

    OK, why did Fortran remove allowing real variables in DO loops?
    I don't think it is to encourage efficient code. (Note that PL/I
    even allows complex and CHAR variables in DO loops.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Mon Mar 28 19:26:31 2022
    On Tuesday, March 29, 2022 at 6:31:15 AM UTC+11, gah4 wrote:
    On Monday, March 28, 2022 at 6:50:52 AM UTC-7, Beliavsky wrote:

    (snip)
    We have been using these PL/I facilities for 55 years.
    Possibly with a 55 year old compiler.

    A number of PL/I compilers are available, including one currently
    under development.

    I was doing both Fortran and PL/I programming in 9th grade.

    My Algebra I book actually had a PL/I chapter, but we conveniently
    skipped over it. That was Fortran IV days, and I found PL/I much
    more fun to program in.

    There are actual stories from those designing PL/I. Among others,
    and I suspect unlike many programming languages, PL/I (or NPL)
    was designed before the first compiler was started.

    (For those interested, there is what Knuth calls Fortran 0, that is,
    the language as it was thought up before the first compiler.)

    In any case, when they were first working on PL/I, they thought about
    making it more compatible with (the then current) Fortran, but decided
    that in the time they had (less than a year) that was not possible.

    That is false. They decided that is was not possible to make FORTRAN VI
    (as PL/I was first called) compatible with FORTRAN IV, and that
    it was therefore necessary to embark on designing a new language
    having substantially better facilities than FORTRAN. This language
    would include facilities for both scientific and commercial computations.

    One result of designing before implementation, is that come features
    turned out harder to implement than they might have thought.
    (And especially considering the smaller and slower computers
    of the time.) Many original PL/I features have now made it into
    Fortran, close to 60 years later. It is also interesting to see the
    ones that haven't.

    For one, PL/I had generic intrinsic functions from the beginning,
    and still more generic than Fortran. You can, for example, call
    SQRT with an integer (that is, fixed point) argument. Since PL/I
    allows fixed point types with the radix point other than just to the
    right of the LSD, that makes sense. (In many cases, values are
    converted to double precision floating point, and that is used
    for the actual function call.) And yet Fortran still doesn't do that.

    (PL/I will even let you call SQRT with a CHAR argument, and do
    the conversion for you, if the value looks like a number.)

    Sometimes it looks to me that when features are added to Fortran,
    they try to make it as hard as possible for users to use them.
    Complicated rules are added, so that both compiler writers
    and programmers have a hard time figuring them out.

    It looks to me like PL/I tends to have simpler rules, though
    sometimes harder for compiler writers.

    But yes, there aren't enough PL/I users to get compilers writers
    interested, and not enough compilers to get users interested.

    A PL/I compiler is currently under development, already implementing
    most of PL/I.

    And of course, IBM is still developing its PL/I compiler.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Gary Scott on Mon Mar 28 19:27:41 2022
    On Tuesday, March 29, 2022 at 8:46:07 AM UTC+11, Gary Scott wrote:

    Some of those "features" of PL/I do not encourage the most efficient
    code. Fortran in some ways forces you to think in ways that encourage execution efficiency.

    Such as?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to All on Mon Mar 28 20:55:08 2022
    On Monday, March 28, 2022 at 3:31:15 PM UTC-4, gah4 wrote:
    ..
    But yes, there aren't enough PL/I users to get compilers writers
    interested, and not enough compilers to get users interested.

    PL/I appears to many to have tried to be a language "that did everything".

    There have been many "imitators" since, they go by C++ and its variants.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to gah4@u.washington.edu on Tue Mar 29 05:39:21 2022
    gah4 <gah4@u.washington.edu> schrieb:

    OK, why did Fortran remove allowing real variables in DO loops?
    I don't think it is to encourage efficient code. (Note that PL/I
    even allows complex and CHAR variables in DO loops.)

    I don't have a first-hand account of why it happened, but there
    is a strong suspect: Rounding errors leading to uncertainties
    about the number of iterations.

    While there is little doubt about the intended semantics of

    DO R = 0.,10.,0.5

    there is likely to be problems with

    DO R = 0., 10, 0.1

    (I'm not 100% convinced about that, since one might
    as well write

    DO R = 0., 10.05, 0.1

    or

    DO R=0., 9.95, 0.1

    but I suspect that people got it wrong a lot).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fiziqs@gmail.com@21:1/5 to Robin Vowels on Tue Mar 29 03:33:54 2022
    On Tuesday, March 29, 2022 at 4:26:33 AM UTC+2, Robin Vowels wrote:

    But yes, there aren't enough PL/I users to get compilers writers interested, and not enough compilers to get users interested.
    A PL/I compiler is currently under development, already implementing
    most of PL/I.

    And of course, IBM is still developing its PL/I compiler.

    For Fortran, there are a number of both open and closed source compilers with large user bases and developer communities. That means, that one is almost certain not to have to rewrite anything in a new language just because the old one is not supported
    any more or not available on a new platform. The IBM one is neither cheap nor widely marketed, and the other one is closed source, developed by a rather small company. Also, there is an alternative complicated language with all the features one might
    imagine, that has a number of both open and closed source compilers, in addition to a large user base, namely C++.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gary Scott@21:1/5 to fiz...@gmail.com on Tue Mar 29 09:01:35 2022
    On 3/29/2022 5:33 AM, fiz...@gmail.com wrote:
    On Tuesday, March 29, 2022 at 4:26:33 AM UTC+2, Robin Vowels wrote:

    But yes, there aren't enough PL/I users to get compilers writers
    interested, and not enough compilers to get users interested.
    A PL/I compiler is currently under development, already implementing
    most of PL/I.

    And of course, IBM is still developing its PL/I compiler.

    For Fortran, there are a number of both open and closed source compilers with large user bases and developer communities. That means, that one is almost certain not to have to rewrite anything in a new language just because the old one is not supported
    any more or not available on a new platform. The IBM one is neither cheap nor widely marketed, and the other one is closed source, developed by a rather small company. Also, there is an alternative complicated language with all the features one might
    imagine, that has a number of both open and closed source compilers, in addition to a large user base,

    namely C++.

    yes...but yuck...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Thomas Koenig on Tue Mar 29 11:16:49 2022
    On Monday, March 28, 2022 at 10:39:24 PM UTC-7, Thomas Koenig wrote:
    gah4 <ga...@u.washington.edu> schrieb:
    OK, why did Fortran remove allowing real variables in DO loops?
    I don't think it is to encourage efficient code. (Note that PL/I
    even allows complex and CHAR variables in DO loops.)

    I don't have a first-hand account of why it happened, but there
    is a strong suspect: Rounding errors leading to uncertainties
    about the number of iterations.

    While there is little doubt about the intended semantics of

    DO R = 0.,10.,0.5

    there is likely to be problems with

    DO R = 0., 10, 0.1

    (I'm not 100% convinced about that, since one might
    as well write

    DO R = 0., 10.05, 0.1

    or

    DO R=0., 9.95, 0.1

    but I suspect that people got it wrong a lot).

    Well, yes. But for me, it isn't up to the compiler to force me,
    (and in only one specific case) to avoid rounding errors.

    So, okay, the language can be designed to encourage efficient code,
    but it shouldn't require it.

    The actual reason this one bothers me, is that when I was younger
    I would sometimes translate BASIC programs to Fortran, from
    implementations that only have a floating point type.

    Maybe it is too long ago now, but remember that the product
    that made Microsoft is a BASIC interpreter. Millions of people
    started programming on such systems, where FOR loops only
    have a floating point type.

    The one case I can imagine where a Fortran user might really
    want to use a floating point DO loop is labels for a plot axis.
    And really, if one is close enough to run into that, it isn't likely
    to be the worst thing that could happen. But good programmers
    will add a small amount to be sure.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to All on Wed Mar 30 00:28:12 2022
    On 3/29/22 1:16 PM, gah4 wrote:
    On Monday, March 28, 2022 at 10:39:24 PM UTC-7, Thomas Koenig wrote:
    gah4 <ga...@u.washington.edu> schrieb:
    OK, why did Fortran remove allowing real variables in DO loops?
    I don't think it is to encourage efficient code. (Note that PL/I
    even allows complex and CHAR variables in DO loops.)

    I don't have a first-hand account of why it happened, but there
    is a strong suspect: Rounding errors leading to uncertainties
    about the number of iterations.

    While there is little doubt about the intended semantics of

    DO R = 0.,10.,0.5

    there is likely to be problems with

    DO R = 0., 10, 0.1

    (I'm not 100% convinced about that, since one might
    as well write

    DO R = 0., 10.05, 0.1

    or

    DO R=0., 9.95, 0.1

    but I suspect that people got it wrong a lot).

    Well, yes. But for me, it isn't up to the compiler to force me,
    (and in only one specific case) to avoid rounding errors.

    So, okay, the language can be designed to encourage efficient code,
    but it shouldn't require it.

    It isn't necessarily efficient code in this case, it is code that
    doesn't surprise the programmer. I personally was glad to see this
    feature dropped.


    The actual reason this one bothers me, is that when I was younger
    I would sometimes translate BASIC programs to Fortran, from
    implementations that only have a floating point type.

    Yeah, BASIC should not be the model programming language for fortran.

    Ok, here is the problem with floating point loops in fortran. I don't
    know how BASIC designed their loops, but in fortran, the first thing
    that happens is that the trip count is evaluated. That determines the
    number of iterations of the loop (excepting early exits, etc.).

    Then the loop index is initialized and its value is incremented each
    pass through the loop. See the problem now? In floating point
    arithmetic, roundoff errors can accumulate for the floating point index
    value, so during the final loop iteration, its value can be less than
    the upper bound (surprising the programmer who thinks there should have
    been additional passes through the loop body), or it can be greater than
    the upper bound (surprising the programmer who thinks extra iterations
    were performed by mistake.

    Except for some exceptional situations where the loop ranges and indexes
    occur without rounding error, either one or the other of those two
    surprising things happens. In other words, in the typical situation, the programmer is surprised. That is the sign that this was a poorly
    designed feature to begin with. Another sign is that the rounding errors
    can change depending on how the rounding mode is set at the time the
    loop is executed, or it can change with compiler optimization level,
    where the increment is done in different ways or using a different
    instruction sequence.

    So no matter how you look at it, it was a poor language design choice.
    And doing loops with integer counters, which does not suffer from this
    kind of roundoff error, is not only easy, sometimes the code is even
    simpler and easier to understand. And yes, as you point out, it may be
    more efficient too.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Ron Shepard on Wed Mar 30 06:19:45 2022
    On Tuesday, March 29, 2022 at 10:28:17 PM UTC-7, Ron Shepard wrote:
    On 3/29/22 1:16 PM, gah4 wrote:

    (snip)
    The actual reason this one bothers me, is that when I was younger
    I would sometimes translate BASIC programs to Fortran, from
    implementations that only have a floating point type.

    Yeah, BASIC should not be the model programming language for fortran.

    Ok, here is the problem with floating point loops in fortran. I don't
    know how BASIC designed their loops, but in fortran, the first thing
    that happens is that the trip count is evaluated. That determines the
    number of iterations of the loop (excepting early exits, etc.).

    Yes. But even so, I don't believe that it should be up to compilers
    (and language designers) to decide.

    And yes that might give different results than the more usual loop and
    compare structure.

    Then the loop index is initialized and its value is incremented each
    pass through the loop. See the problem now? In floating point
    arithmetic, roundoff errors can accumulate for the floating point index value, so during the final loop iteration, its value can be less than
    the upper bound (surprising the programmer who thinks there should have
    been additional passes through the loop body), or it can be greater than
    the upper bound (surprising the programmer who thinks extra iterations
    were performed by mistake.

    There are (maybe a small number of) cases where the programmer
    doesn't care. And also, as noted, there the rounding was considered
    in advance. In addition, this will mostly go away when decimal floating
    point gets more popular.

    Except for some exceptional situations where the loop ranges and indexes occur without rounding error, either one or the other of those two
    surprising things happens. In other words, in the typical situation, the programmer is surprised. That is the sign that this was a poorly
    designed feature to begin with. Another sign is that the rounding errors
    can change depending on how the rounding mode is set at the time the
    loop is executed, or it can change with compiler optimization level,
    where the increment is done in different ways or using a different instruction sequence.

    So no matter how you look at it, it was a poor language design choice.
    And doing loops with integer counters, which does not suffer from this
    kind of roundoff error, is not only easy, sometimes the code is even
    simpler and easier to understand. And yes, as you point out, it may be
    more efficient too.

    There are some interesting Java features designed to avoid problems
    that C programmers make. One is that scalar variables, including
    reference variables, are required to be initialized before use, in a way
    that the compiler can verify. There are cases where the compiler
    can't verify, though, in which case the usual solution is to just put
    an initializer on the declaration. (Which C and Java allow for auto variables.)

    On the other hand, arrays (which are objects) are always zero
    (or false) when created. It is too hard for the compiler to verify
    that every array element is assigned before use.

    Another funny (for C programmers) Java feature is designed to
    avoid the common C mistake of writing

    if(x=y) ...

    when one meant to write

    if(x==y) ...

    C if statements consider anything non-zero (or non-null pointer) as true,
    but Java only allows a boolean expression. So,

    if(x=y) ...

    is only legal for boolean x and y, which is rare enough.

    But both of those are to catch mistakes by programmers, where
    they didn't write what they (presumably) meant to write.

    I suppose it is possible for someone to accidentally write a REAL DO
    loop, but it doesn't seem so likely. And especially unlikely to
    for the case of non-integer increment value.

    And Fortran still allows you to make all kinds of other rounding
    errors, including in IF statements, maybe even in loops!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Wed Mar 30 17:52:09 2022
    On Thursday, March 31, 2022 at 12:19:47 AM UTC+11, gah4 wrote:

    And Fortran still allows you to make all kinds of other rounding
    errors, including in IF statements, maybe even in loops!

    Silverfrost F95 warns when you compare REALs in an IF statement.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Robin Vowels on Wed Mar 30 19:06:52 2022
    On Wednesday, March 30, 2022 at 5:52:11 PM UTC-7, Robin Vowels wrote:
    On Thursday, March 31, 2022 at 12:19:47 AM UTC+11, gah4 wrote:

    And Fortran still allows you to make all kinds of other rounding
    errors, including in IF statements, maybe even in loops!
    Silverfrost F95 warns when you compare REALs in an IF statement.

    I wouldn't be against a warning for DO statements.

    By the way:

    DCL I FIXED BIN(31,0) COMPLEX;
    DO I=1+1I BY 1+1I WHILE(ABS(I)<200);
    PUT SKIP LIST(I, I**I,SQRT(I));
    END;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Thu Mar 31 21:17:24 2022
    On Thursday, March 31, 2022 at 1:06:54 PM UTC+11, gah4 wrote:
    On Wednesday, March 30, 2022 at 5:52:11 PM UTC-7, Robin Vowels wrote:
    On Thursday, March 31, 2022 at 12:19:47 AM UTC+11, gah4 wrote:

    And Fortran still allows you to make all kinds of other rounding
    errors, including in IF statements, maybe even in loops!
    .
    Silverfrost F95 warns when you compare REALs in an IF statement.
    I wouldn't be against a warning for DO statements.

    By the way:

    DCL I FIXED BIN(31,0) COMPLEX;
    DO I=1+1I BY 1+1I WHILE(ABS(I)<200);
    PUT SKIP LIST(I, I**I,SQRT(I));
    END;
    .
    This would never have run to completion using the PL/I-F compiler,
    for floating-point overflow would have occurred at around the 50th
    iteration.
    .
    It won't compile because the BY option cannot be COMPLEX.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to All on Thu Mar 31 23:53:43 2022
    On Thursday, March 31, 2022 at 9:17:26 PM UTC-7, Robin Vowels wrote:

    (snip, I wrote)

    DCL I FIXED BIN(31,0) COMPLEX;
    DO I=1+1I BY 1+1I WHILE(ABS(I)<200);
    PUT SKIP LIST(I, I**I,SQRT(I));
    END;

    This would never have run to completion using the PL/I-F compiler,
    for floating-point overflow would have occurred at around the 50th
    iteration.

    It won't compile because the BY option cannot be COMPLEX.

    I actually didn't try that one, but one I did 45 years ago:

    DCL (A, B, C, D) CHAR(20);
    B='1';
    C='. 100';
    D='1';
    DO A=B TO C BY D;
    PUT SKIP LIST(A, SQRT(A));
    END;

    So, I don't know if BY can be COMPLEX, but I
    do know that it can be CHAR.
    (And the sqrt are double precision.)

    (How I knew that 45 years ago, I am not sure.)

    And the loop test is done as a character comparison, not
    a numeric comparison. The blanks in C are important.

    And I won't ask when Fortran gets COMPLEX or CHARACTER
    DO loops.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Fri Apr 1 04:20:53 2022
    On Friday, April 1, 2022 at 5:53:45 PM UTC+11, gah4 wrote:
    On Thursday, March 31, 2022 at 9:17:26 PM UTC-7, Robin Vowels wrote:

    (snip, I wrote)
    DCL I FIXED BIN(31,0) COMPLEX;
    DO I=1+1I BY 1+1I WHILE(ABS(I)<200);
    PUT SKIP LIST(I, I**I,SQRT(I));
    END;
    This would never have run to completion using the PL/I-F compiler,
    for floating-point overflow would have occurred at around the 50th iteration.
    It won't compile because the BY option cannot be COMPLEX.
    .
    IBM's PL/I Language Specification manuals C28-6571-1 of 1965
    and C28-6571-3 of 1966
    give an example of a complex constant as a BY component.
    Whether these were actually implemented is not known;
    both manuals state that not all these facilities will be implemented
    in the first release of the compiler.
    If complex BY was available in 1966, your segment would
    have compiled and run, subject to the limit mentioned above
    of some 50 iterations.
    .
    However, a complex BY is not available in Windows PL/I.
    .
    I actually didn't try that one, but one I did 45 years ago:

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Mon Apr 4 01:31:37 2022
    On Friday, April 1, 2022 at 5:53:45 PM UTC+11, gah4 wrote:
    On Thursday, March 31, 2022 at 9:17:26 PM UTC-7, Robin Vowels wrote:

    (snip, I wrote)
    DCL I FIXED BIN(31,0) COMPLEX;
    DO I=1+1I BY 1+1I WHILE(ABS(I)<200);
    PUT SKIP LIST(I, I**I,SQRT(I));
    END;
    This would never have run to completion using the PL/I-F compiler,
    for floating-point overflow would have occurred at around the 50th iteration.
    It won't compile because the BY option cannot be COMPLEX.
    I actually didn't try that one, but one I did 45 years ago:

    DCL (A, B, C, D) CHAR(20);
    B='1';
    C='. 100';
    D='1';
    DO A=B TO C BY D;
    PUT SKIP LIST(A, SQRT(A));
    END;
    .
    This one won't work.
    Even if the error in the assignment to C were corrected,
    it still won't work.
    The reason?
    Conversion from numeric to character (after the arithmetic)
    introduces leading blanks, that causes inequality when
    the control variable A is compared with C.
    That results in an infinite loop.
    For the code to work, the string constants assigned to both B and C must be written
    as strings containing exactly 18 characters (right adjusted, of course).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Robin Vowels on Mon Apr 4 12:19:28 2022
    On Monday, April 4, 2022 at 1:31:39 AM UTC-7, Robin Vowels wrote:

    (snip)
    I actually didn't try that one, but one I did 45 years ago:

    DCL (A, B, C, D) CHAR(20);
    B='1';
    C='. 100';
    D='1';
    DO A=B TO C BY D;
    PUT SKIP LIST(A, SQRT(A));
    END;

    This one won't work.
    Even if the error in the assignment to C were corrected,
    it still won't work.
    The reason?
    Conversion from numeric to character (after the arithmetic)
    introduces leading blanks, that causes inequality when
    the control variable A is compared with C.
    That results in an infinite loop.
    For the code to work, the string constants assigned to both B and C must be written
    as strings containing exactly 18 characters (right adjusted, of course).

    The period seems to be from my computer believing it is the end of a sentence, and adding it when I wasn't looking.

    As well as I remember from 45 years ago, it needs three blanks before the 100 to match the result of the conversion. That might be different for different systems,
    though. But yes, with no blanks it is an infinite loop, and did work 45 years ago.

    I also had a:
    I = 0;
    DO IMAG(I) = 1 TO 100;
    PUT SKIP LIST(I, I**I);
    END;

    loop, which also worked, and the first time I learned that
    1I**1I is real, but the other ones are not.

    If Fortran allowed real DO loops, then

    DO I%IM = 1, 100

    (Or if Fortran had something like:

    DCL I FIXED BIN(31,0) COMPLEX;

    that is, an integer complex data type.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)