• SAVE statement in module

    From Arjan@21:1/5 to All on Wed Feb 16 07:34:31 2022
    Hi,

    I somehow never used the SAVE statement. Recently, I got a model that starts all of its modules with lines of the following sort:

    MODULE XXX
    USE YYY
    IMPLICIT NONE
    SAVE
    PRIVATE
    PUBLIC :: Blah

    I know about using SAVE for particular subroutines. Am I right in understanding that the above construction simply applies SAVE to everything that is part of the module?

    I never thought about using this statement in this way. Is it good (= defensive) programming? Or would you recommend finding out which subroutines/functions actually use this feature and move SAVE to those particular cases to explicitly show where is is
    used? To me the general application in the header of a module seems a bit "lazy", but I may be wrong.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steve Lionel@21:1/5 to Arjan on Wed Feb 16 13:09:31 2022
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in understanding that the above construction simply applies SAVE to everything that is part of the module?

    Yes, but it's a no-op, since module variables are now stated to have the
    SAVE attribute by default. In earlier standards, there was complicated
    wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't
    know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.

    --
    Steve Lionel
    ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
    Retired Intel Fortran developer/support
    Email: firstname at firstnamelastname dot com
    Twitter: @DoctorFortran
    LinkedIn: https://www.linkedin.com/in/stevelionel
    Blog: https://stevelionel.com/drfortran
    WG5: https://wg5-fortran.org

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lynn McGuire@21:1/5 to Steve Lionel on Wed Feb 16 16:10:34 2022
    On 2/16/2022 12:09 PM, Steve Lionel wrote:
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in
    understanding that the above construction simply applies SAVE to
    everything that is part of the module?

    Yes, but it's a no-op, since module variables are now stated to have the
    SAVE attribute by default. In earlier standards, there was complicated wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't
    know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Lynn McGuire on Wed Feb 16 19:36:12 2022
    On Wednesday, February 16, 2022 at 5:10:40 PM UTC-5, Lynn McGuire wrote:
    On 2/16/2022 12:09 PM, Steve Lionel wrote:
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in
    understanding that the above construction simply applies SAVE to
    everything that is part of the module?

    Yes, but it's a no-op, since module variables are now stated to have the SAVE attribute by default. In earlier standards, there was complicated wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.
    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jfh@21:1/5 to Steve Lionel on Thu Feb 17 12:57:04 2022
    On Thursday, February 17, 2022 at 7:09:37 AM UTC+13, Steve Lionel wrote:
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in understanding that the above construction simply applies SAVE to everything that is part of the module?
    Yes, but it's a no-op, since module variables are now stated to have the
    SAVE attribute by default. In earlier standards, there was complicated wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't
    know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.

    --
    Steve Lionel
    ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
    Retired Intel Fortran developer/support
    Email: firstname at firstnamelastname dot com
    Twitter: @DoctorFortran
    LinkedIn: https://www.linkedin.com/in/stevelionel
    Blog: https://stevelionel.com/drfortran
    WG5: https://wg5-fortran.org

    Thank you Steve. Are variables local to module procedures module variables SAVEd by default?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lynn McGuire@21:1/5 to Beliavsky on Thu Feb 17 16:37:04 2022
    On 2/16/2022 9:36 PM, Beliavsky wrote:
    On Wednesday, February 16, 2022 at 5:10:40 PM UTC-5, Lynn McGuire wrote:
    On 2/16/2022 12:09 PM, Steve Lionel wrote:
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in
    understanding that the above construction simply applies SAVE to
    everything that is part of the module?

    Yes, but it's a no-op, since module variables are now stated to have the >>> SAVE attribute by default. In earlier standards, there was complicated
    wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't >>> know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.
    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software.

    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steve Lionel@21:1/5 to jfh on Thu Feb 17 18:51:36 2022
    On 2/17/2022 3:57 PM, jfh wrote:
    Thank you Steve. Are variables local to module procedures module variables SAVEd by default?

    No - those are not module variables.

    --
    Steve Lionel
    ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
    Retired Intel Fortran developer/support
    Email: firstname at firstnamelastname dot com
    Twitter: @DoctorFortran
    LinkedIn: https://www.linkedin.com/in/stevelionel
    Blog: https://stevelionel.com/drfortran
    WG5: https://wg5-fortran.org

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Steve Lionel on Thu Feb 17 16:51:18 2022
    On Thursday, February 17, 2022 at 3:51:40 PM UTC-8, Steve Lionel wrote:
    On 2/17/2022 3:57 PM, jfh wrote:
    Thank you Steve. Are variables local to module procedures module variables SAVEd by default?
    No - those are not module variables.

    Can you explain this a little more, maybe with a (one or two line) example?

    I know whath module procedures are, and so module procedure variables,
    but I am not so sure about module procedure module variables.

    So module variables inside a module procedure are not module variables?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to gah4@u.washington.edu on Fri Feb 18 07:27:31 2022
    gah4 <gah4@u.washington.edu> schrieb:
    On Thursday, February 17, 2022 at 3:51:40 PM UTC-8, Steve Lionel wrote:
    On 2/17/2022 3:57 PM, jfh wrote:
    Thank you Steve. Are variables local to module procedures module variables SAVEd by default?
    No - those are not module variables.

    Can you explain this a little more, maybe with a (one or two line) example?

    module foo
    integer :: n ! This is a module variable
    contains
    subroutine bar
    integer :: j ! This is not a module variable
    end subroutine bar
    end module

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From pehache@21:1/5 to All on Fri Feb 18 08:55:57 2022
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software.



    Writing code is a lot of work. The declaration/initialisation is always supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the
    initialised variable need to initialisation to zero.

    --
    "...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
    même sens que les tiennes.", ST sur fr.bio.medecine
    ST passe le mur du çon : <j3nn2hFmqj7U1@mid.individual.net>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lynn McGuire@21:1/5 to Thomas Koenig on Fri Feb 18 13:49:01 2022
    On 2/18/2022 1:27 AM, Thomas Koenig wrote:
    gah4 <gah4@u.washington.edu> schrieb:
    On Thursday, February 17, 2022 at 3:51:40 PM UTC-8, Steve Lionel wrote:
    On 2/17/2022 3:57 PM, jfh wrote:
    Thank you Steve. Are variables local to module procedures module variables SAVEd by default?
    No - those are not module variables.

    Can you explain this a little more, maybe with a (one or two line) example?

    module foo
    integer :: n ! This is a module variable
    contains
    subroutine bar
    integer :: j ! This is not a module variable
    end subroutine bar
    end module

    Thanks !

    Modules are new to me too.

    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Lynn McGuire on Fri Feb 18 20:08:06 2022
    Lynn McGuire <lynnmcguire5@gmail.com> schrieb:
    On 2/18/2022 1:55 AM, pehache wrote:

    Writing code is a lot of work. The declaration/initialisation is always
    supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the
    initialised variable need to initialisation to zero.

    Which ones need initialization and which ones don't ?

    Hard to know decades after the code has been written, usually.

    Explicitly initializing everything with a signalling NaN (if
    supported) would certainly help in spotting problems.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lynn McGuire@21:1/5 to pehache on Fri Feb 18 13:48:14 2022
    On 2/18/2022 1:55 AM, pehache wrote:
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software.



    Writing code is a lot of work. The declaration/initialisation is always supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the initialised variable need to initialisation to zero.

    Which ones need initialization and which ones don't ?

    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Lynn McGuire on Fri Feb 18 17:40:00 2022
    On Friday, February 18, 2022 at 9:37:08 AM UTC+11, Lynn McGuire wrote:
    On 2/16/2022 9:36 PM, Beliavsky wrote:
    On Wednesday, February 16, 2022 at 5:10:40 PM UTC-5, Lynn McGuire wrote:
    On 2/16/2022 12:09 PM, Steve Lionel wrote:
    On 2/16/2022 10:34 AM, Arjan wrote:
    I know about using SAVE for particular subroutines. Am I right in
    understanding that the above construction simply applies SAVE to
    everything that is part of the module?

    Yes, but it's a no-op, since module variables are now stated to have the >>> SAVE attribute by default. In earlier standards, there was complicated >>> wording about modules being "active", the way the standard still
    describes COMMON from the days of overlays (19.6.6(3)(b)), and we didn't >>> know of a single F90+ implementation that didn't make all module
    variables SAVE anyway.
    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main
    .
    That is a lot of work for the 300,000+ local variables in my software.
    .
    You have said that before.
    what can you expect for non-standard code.
    Anyway, something like that can be automated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lynn McGuire@21:1/5 to Robin Vowels on Fri Feb 18 20:00:37 2022
    On 2/18/2022 7:42 PM, Robin Vowels wrote:
    On Saturday, February 19, 2022 at 6:48:19 AM UTC+11, Lynn McGuire wrote:
    On 2/18/2022 1:55 AM, pehache wrote:
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software. >>>>

    Writing code is a lot of work. The declaration/initialisation is always
    supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the
    initialised variable need to initialisation to zero.
    Which ones need initialization and which ones don't ?
    .
    Initialize them all.

    Except the subroutine and function arguments.

    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Lynn McGuire on Fri Feb 18 17:42:07 2022
    On Saturday, February 19, 2022 at 6:48:19 AM UTC+11, Lynn McGuire wrote:
    On 2/18/2022 1:55 AM, pehache wrote:
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software.


    Writing code is a lot of work. The declaration/initialisation is always supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the initialised variable need to initialisation to zero.
    Which ones need initialization and which ones don't ?
    .
    Initialize them all.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Lynn McGuire on Sat Feb 19 01:31:59 2022
    On Saturday, February 19, 2022 at 1:00:41 PM UTC+11, Lynn McGuire wrote:
    On 2/18/2022 7:42 PM, Robin Vowels wrote:
    On Saturday, February 19, 2022 at 6:48:19 AM UTC+11, Lynn McGuire wrote:
    On 2/18/2022 1:55 AM, pehache wrote:
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ? >>>>>>
    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software. >>>>

    Writing code is a lot of work. The declaration/initialisation is always >>> supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the
    initialised variable need to initialisation to zero.
    Which ones need initialization and which ones don't ?
    .
    Initialize them all.
    Except the subroutine and function arguments.
    .
    I think that you mean the dummy arguments.
    .
    These are not local variables. A dummy argument is a dummy argument.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From pehache@21:1/5 to All on Sat Feb 19 10:49:28 2022
    Le 18/02/2022 à 20:48, Lynn McGuire a écrit :
    On 2/18/2022 1:55 AM, pehache wrote:
    Le 17/02/2022 à 23:37, Lynn McGuire a écrit :

    Does SAVE automatically initialize all listed variables to zero ?

    Thanks,
    Lynn

    No, but you can initialize variables in the declaration:

    module m
    implicit none
    integer, save :: i = 42
    end module m
    !
    program main
    use m
    implicit none
    print*,"i=",i ! 42
    end program main

    That is a lot of work for the 300,000+ local variables in my software.



    Writing code is a lot of work. The declaration/initialisation is
    always supposed to be a very minor part of any code.

    Plus, not all the variables need to be initialised, and not all the
    initialised variable need to initialisation to zero.

    Which ones need initialization and which ones don't ?

    When you write a code you know that


    --
    "...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
    même sens que les tiennes.", ST sur fr.bio.medecine
    ST passe le mur du çon : <j3nn2hFmqj7U1@mid.individual.net>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JCampbell@21:1/5 to All on Sat Feb 19 23:23:42 2022
    "SAVE" and "initialise" are very different.
    I have assumed SAVE for global data is not necessary. I have mostly assumed both COMMON and MODULE to have global scope, except for the use of overlays on pre extended memory PC's, which I have mostly forgotten and I hope is forgotten. I don't understand
    the scare campaign of COMMON or MODULE going out of scope.
    MODULE combined with derived types is a great way to define the memory data structures, which can feature initialised data.
    I avoid SAVE for local variables/arrays, which is incompatible with recursive or OpenMP approaches.

    Initialise, especially default initialise can be very dangerous/expensive(?), as it demands memory be allocated to any initialised arrays in a Module/Common at startup. It can (has) also produce a very large .exe, depending on the linker approach.
    I prefer to initialise variables and arrays as they are being used. When I was taught FORTRAN, it was an error to use an un-initialised variable, so assuming default initialisation is wrong to me.
    I avoid default initialisation of arrays.

    BLOCK DATA subprograms had a use as they documented which common variables were initialised. I thing these COMMON were allocated a different address class during linking, although this approch has been lost. This identification of initialised module data
    as special, is something that the modern MODULE approach does not highlight.

    Default Initialising large arrays will eat memory. I have seen compilers that offer default initialising of large allocatable arrays. This removes any strategy of minimising/delaying physical memory usage, (which is not always an issue)
    Is there a 2 GByte limit of initialised variables with some linkers ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to JCampbell on Sun Feb 20 00:33:31 2022
    On Sunday, February 20, 2022 at 6:23:46 PM UTC+11, JCampbell wrote:
    "SAVE" and "initialise" are very different.
    I have assumed SAVE for global data is not necessary. I have mostly assumed both COMMON and MODULE to have global scope, except for the use of overlays on pre extended memory PC's, which I have mostly forgotten and I hope is forgotten. I don't
    understand the scare campaign of COMMON or MODULE going out of scope.
    MODULE combined with derived types is a great way to define the memory data structures, which can feature initialised data.
    I avoid SAVE for local variables/arrays, which is incompatible with recursive or OpenMP approaches.

    Initialise, especially default initialise can be very dangerous/expensive(?), as it demands memory be allocated to any initialised arrays in a Module/Common at startup. It can (has) also produce a very large .exe, depending on the linker approach.
    I prefer to initialise variables and arrays as they are being used. When I was taught FORTRAN,
    it was an error to use an un-initialised variable,
    .
    It still is.
    .
    so assuming default initialisation is wrong to me.
    I avoid default initialisation of arrays.
    BLOCK DATA subprograms had a use as they documented which common variables were initialised. I thing these COMMON were allocated a different address class during linking, although this approch has been lost. This identification of initialised module
    data as special, is something that the modern MODULE approach does not highlight.

    Default Initialising large arrays will eat memory. I have seen compilers that offer default initialising of large allocatable arrays. This removes any strategy of minimising/delaying physical memory usage, (which is not always an issue)
    Is there a 2 GByte limit of initialised variables with some linkers ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to JCampbell on Sun Feb 20 12:14:26 2022
    On 2/20/22 1:23 AM, JCampbell wrote:
    "SAVE" and "initialise" are very different.
    I have assumed SAVE for global data is not necessary. I have mostly assumed both COMMON and MODULE to have global scope, except for the use of overlays on pre extended memory PC's, which I have mostly forgotten and I hope is forgotten.

    I think global scope and whether data is required to retain old values
    are two different issues, related, but different.

    I don't understand the scare campaign of COMMON or MODULE going out of scope.

    Common and modules have global scope in the sense that a program can
    access them at any level in the subprogram calling sequence. However, it
    is not until the recent fortran revisions that they were required to
    retain their old values globally. That was why SAVE was introduced for
    common blocks in f77, in order to define exactly when the previous
    values were required to be saved and when they weren't. So it was not
    really "scare tactics", it was just recognizing the semantics of the
    language over the last 45 years.

    MODULE combined with derived types is a great way to define the memory data structures, which can feature initialised data.
    I avoid SAVE for local variables/arrays, which is incompatible with recursive or OpenMP approaches.

    Yes, there are times when SAVE is necessary, and there are times when
    SAVE should be avoided.


    Initialise, especially default initialise can be very dangerous/expensive(?), as it demands memory be allocated to any initialised arrays in a Module/Common at startup. It can (has) also produce a very large .exe, depending on the linker approach.
    I prefer to initialise variables and arrays as they are being used. When I was taught FORTRAN, it was an error to use an un-initialised variable, so assuming default initialisation is wrong to me.
    I avoid default initialisation of arrays.

    I don't disagree with this. There are times when fortran initialization
    should be avoided and assignments should be used instead (to
    "initialize" entities using the common meaning of the term).

    However, a nice feature would be the ability to initialize allocatable
    scalars and arrays. This would eliminate a common class of program
    errors, and simplify the use of allocatable entities. So in these cases,
    it would be better if the language had more opportunities to initialize entities, not less, and if programmers used that capability more, not less.

    I also think that initialization of pointers (other than to nul()) would
    be useful. This might have even made the cut in one of the recent J3
    decisions, I'm not sure.

    BLOCK DATA subprograms had a use as they documented which common variables were initialised.

    Block data is the only way to initialize entities in common blocks. Any
    other initializations you might see are compiler extensions.

    I thing these COMMON were allocated a different address class during linking, although this approch has been lost. This identification of initialised module data as special, is something that the modern MODULE approach does not highlight.

    I don't understand this sentence. In f77, block data was the only way to initialize data in common blocks, which in turn were the only global
    data structures in the language. With f90+, global entities can be in
    modules too, and initialization of those entities can occur in several
    new ways.


    Default Initialising large arrays will eat memory.

    Yes, default initialization of components of user defined data types can
    be inefficient, and at the same time it can be an excellent way to
    simplify the logic of a program. Namely, if you know that an entity has
    default initialization in its definition, then you NEVER need to test to
    see if the entity has been initialized before using it. That is exactly
    why I think both initialization and default initialization should be
    allowed for allocatable entities and pointers.

    I have seen compilers that offer default initialising of large allocatable arrays.

    I have not seen this. Which compilers allow default initialization of components that are allocatable arrays? Which compilers allow
    initialization of any allocatable entities?

    This removes any strategy of minimising/delaying physical memory usage, (which is not always an issue)
    Is there a 2 GByte limit of initialised variables with some linkers ?

    Whether to initialize (common meaning) an entity at its declaration or
    with an executable statement is a decision the programmer makes based on several facets, including memory usage, runtime efficiency, and
    algorithm requirements. Sometimes, those different facets of the problem
    are in conflict. I do not think there is an acceptable universal answer
    for all cases, so that conflict is an essential, and important, aspect
    of programming in fortran.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steve Lionel@21:1/5 to JCampbell on Sun Feb 20 14:13:10 2022
    On 2/20/2022 2:23 AM, JCampbell wrote:
    I have assumed SAVE for global data is not necessary. I have mostly assumed both COMMON and MODULE to have global scope, except for the use of overlays on pre extended memory PC's, which I have mostly forgotten and I hope is forgotten. I don't
    understand the scare campaign of COMMON or MODULE going out of scope.
    MODULE combined with derived types is a great way to define the memory data structures, which can feature initialised data.

    The bit about modules going out of scope is no longer in the language,
    so module variables now have SAVE implicitly, but the words
    (19.6.6(3)(b)) about COMMON not being active are still there.

    --
    Steve Lionel
    ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
    Retired Intel Fortran developer/support
    Email: firstname at firstnamelastname dot com
    Twitter: @DoctorFortran
    LinkedIn: https://www.linkedin.com/in/stevelionel
    Blog: https://stevelionel.com/drfortran
    WG5: https://wg5-fortran.org

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to Ron Shepard on Sun Feb 20 12:32:30 2022
    On Sunday, February 20, 2022 at 1:14:33 PM UTC-5, Ron Shepard wrote:
    On 2/20/22 1:23 AM, JCampbell wrote:
    "SAVE" and "initialise" are very different.
    I have assumed SAVE for global data is not necessary. I have mostly assumed both COMMON and MODULE to have global scope, except for the use of overlays on pre extended memory PC's, which I have mostly forgotten and I hope is forgotten.
    I think global scope and whether data is required to retain old values
    are two different issues, related, but different.
    I don't understand the scare campaign of COMMON or MODULE going out of scope.
    Common and modules have global scope in the sense that a program can
    access them at any level in the subprogram calling sequence. However, it
    is not until the recent fortran revisions that they were required to
    retain their old values globally. That was why SAVE was introduced for
    common blocks in f77, in order to define exactly when the previous
    values were required to be saved and when they weren't. So it was not
    really "scare tactics", it was just recognizing the semantics of the
    language over the last 45 years.
    MODULE combined with derived types is a great way to define the memory data structures, which can feature initialised data.
    I avoid SAVE for local variables/arrays, which is incompatible with recursive or OpenMP approaches.
    Yes, there are times when SAVE is necessary, and there are times when
    SAVE should be avoided.
    Initialise, especially default initialise can be very dangerous/expensive(?), as it demands memory be allocated to any initialised arrays in a Module/Common at startup. It can (has) also produce a very large .exe, depending on the linker approach.
    I prefer to initialise variables and arrays as they are being used. When I was taught FORTRAN, it was an error to use an un-initialised variable, so assuming default initialisation is wrong to me.
    I avoid default initialisation of arrays.
    I don't disagree with this. There are times when fortran initialization should be avoided and assignments should be used instead (to
    "initialize" entities using the common meaning of the term).

    However, a nice feature would be the ability to initialize allocatable scalars and arrays. This would eliminate a common class of program
    errors, and simplify the use of allocatable entities.

    You can write

    allocate(x(n), source = 0.0)

    or

    x = zeros(n)

    where zeros is an easy function to define. What additional functionality do you want?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to Beliavsky on Mon Feb 21 10:19:28 2022
    On 2/20/22 2:32 PM, Beliavsky wrote:
    On Sunday, February 20, 2022 at 1:14:33 PM UTC-5, Ron Shepard wrote:
    On 2/20/22 1:23 AM, JCampbell wrote:
    [...]
    However, a nice feature would be the ability to initialize allocatable
    scalars and arrays. This would eliminate a common class of program
    errors, and simplify the use of allocatable entities.

    You can write

    allocate(x(n), source = 0.0)

    or

    x = zeros(n)

    where zeros is an easy function to define. What additional functionality do you want?

    I was talking about fortran initialization in that sentence. Your
    examples are initialization in the common meaning of the word with
    executable statements.

    To show one potential problem, your first statement above will fail if
    x(:) is already allocated, so it might be necessary to test the
    allocation status first. Then suppose the above statement might need to
    be executed in many places in the code, both the allocation status query
    and the allocate() statement need to be coupled and always occur
    together. The second form does not need the status query, of course,
    because allocation on assignment works in either case, but there are
    situations where the allocate() statement is necessary and the
    assignment cannot be used.

    For example, for a default initialization situation, the derived type
    might be defined as

    type xxx
    integer :: n = 0
    integer, allocatable :: array(0:0)=[0]
    end type xxx

    Then when an instance of that type is declared, the programmer knows
    that both components have initial values and in particular that the
    array component is always in an allocated state, so it is never
    necessary to test that allocation status before using or modifying it.
    It would be useful to initialize allocatable arrays, character strings,
    and user defined types, sometimes to have zero size, sometimes to have
    nonzero size with initial values.

    This has been discussed here in clf before, and the main objection is
    that allocatable data typically exists in a heap which is not available
    until run time. I understand that argument, but that doesn't seem to be
    serious enough to override all of the obvious advantages of this feature
    to the programmer.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Ron Shepard on Mon Feb 21 09:34:39 2022
    On Monday, February 21, 2022 at 11:19:39 AM UTC-5, Ron Shepard wrote:
    On 2/20/22 2:32 PM, Beliavsky wrote:

    ..
    Then when an instance of that type is declared, the programmer knows
    that both components have initial values and in particular that the
    array component is always in an allocated state, so it is never
    necessary to test that allocation status before using or modifying it.
    It would be useful to initialize allocatable arrays, character strings,
    and user defined types, sometimes to have zero size, sometimes to have nonzero size with initial values.

    This has been discussed here in clf before, and the main objection is
    that allocatable data typically exists in a heap which is not available until run time. I understand that argument, but that doesn't seem to be serious enough to override all of the obvious advantages of this feature
    to the programmer. ..


    @Beliavsky,

    If you don't mind and not take it wrongly coming from me, can you please follow up on this and put together an issue thread at J3-Fortran proposals site at GitHub and also perhaps at Fortran Discourse? I suggest this given your energy and enthusiasm
    with a lot of Fortran language idea proposals at these 2 sites and you will also likely elicit more positive responses on the idea, or at least some useful feedback on it that might then guide future discussions online with this and other similar
    suggestions.

    You will know that suggestions along the lines of "integer, allocatable :: array(0:0)=[0]" have been made often by @Ron Shepard over the years. But, as you know, suggestions by themselves at an online forum usually don't go anywhere to be useful enough
    for the language itself. These suggestions need to be ultimately transformed into a "paper" during a certain but *limited* timeframe when the standards committee is looking at task lists for the next standard revision on their agenda. Only then can
    Fortranners know the standards committee's view on the matter, whether a) it's of priority and b) what are the issues and challenges and what may be possible or not.

    Without such a paper, as you may know, it's as if the idea didn't even exist. Having an issue thread at the J3-Fortran site will be a start toward this and if it catches sufficient interest to get labeled as 'Fortran 202Y', chances become a tad better (
    still no guarantees) for this suggestion re: ALLOCATABLEs to get considered for the next revision.

    Thanks,

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From pehache@21:1/5 to All on Tue Feb 22 10:15:15 2022
    Le 20/02/2022 à 19:14, Ron Shepard a écrit :


    Yes, there are times when SAVE is necessary, and there are times when
    SAVE should be avoided.


    Yep. A good rule is to not use SAVE unless really needed. And to always explicitely add the SAVE attribute when initialising a variable in the declaration.


    --
    "...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
    même sens que les tiennes.", ST sur fr.bio.medecine
    ST passe le mur du çon : <j3nn2hFmqj7U1@mid.individual.net>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Edmondo Giovannozzi@21:1/5 to All on Wed Feb 23 04:14:47 2022
    Il giorno lunedì 21 febbraio 2022 alle 17:19:39 UTC+1 Ron Shepard ha scritto:
    On 2/20/22 2:32 PM, Beliavsky wrote:
    On Sunday, February 20, 2022 at 1:14:33 PM UTC-5, Ron Shepard wrote:
    On 2/20/22 1:23 AM, JCampbell wrote:
    [...]
    However, a nice feature would be the ability to initialize allocatable
    scalars and arrays. This would eliminate a common class of program
    errors, and simplify the use of allocatable entities.

    You can write

    allocate(x(n), source = 0.0)

    or

    x = zeros(n)

    where zeros is an easy function to define. What additional functionality do you want?
    I was talking about fortran initialization in that sentence. Your
    examples are initialization in the common meaning of the word with executable statements.

    To show one potential problem, your first statement above will fail if
    x(:) is already allocated, so it might be necessary to test the
    allocation status first. Then suppose the above statement might need to
    be executed in many places in the code, both the allocation status query
    and the allocate() statement need to be coupled and always occur
    together. The second form does not need the status query, of course,
    because allocation on assignment works in either case, but there are situations where the allocate() statement is necessary and the
    assignment cannot be used.

    For example, for a default initialization situation, the derived type
    might be defined as

    type xxx
    integer :: n = 0
    integer, allocatable :: array(0:0)=[0]
    end type xxx

    Then when an instance of that type is declared, the programmer knows
    that both components have initial values and in particular that the
    array component is always in an allocated state, so it is never
    necessary to test that allocation status before using or modifying it.
    It would be useful to initialize allocatable arrays, character strings,
    and user defined types, sometimes to have zero size, sometimes to have nonzero size with initial values.

    This has been discussed here in clf before, and the main objection is
    that allocatable data typically exists in a heap which is not available until run time. I understand that argument, but that doesn't seem to be serious enough to override all of the obvious advantages of this feature
    to the programmer.

    $.02 -Ron Shepard

    Most of the time I use allocatable or allocatable component of a user defined type in a procedure where they are dummy arguments with intent(out) or local variables. So they are always unallocated at the beginning of the procedure. Adding the
    reallocation on assignment, I rarely need to check their allocation status or deallocate them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to Edmondo Giovannozzi on Thu Feb 24 00:45:23 2022
    On 2/23/22 6:14 AM, Edmondo Giovannozzi wrote:
    [...]
    Most of the time I use allocatable or allocatable component of a user defined type in a procedure where they are dummy arguments with intent(out) or local variables. So they are always unallocated at the beginning of the procedure. Adding the
    reallocation on assignment, I rarely need to check their allocation status or deallocate them.

    Yes, that was my point. They are always unallocated at the beginning
    because there is currently no way to declare them to be in an allocated
    state or an allocated state with values. If that were possible, then
    there are many situations where that would simplify the logic of the
    program.

    Also, with reallocation on assignment, you lose control of the ability
    to specify the lower bound of the array. You must use an allocate()
    statement for that, and the array in the allocate statement must be deallocated, otherwise it is an error. Similarlly, the array must be
    allocated if used in a deallocate statement, otherwise it is an error.
    So the current situation is an intertangled mess of conditions and
    constraints, all leading to a lot of complicated code logic.

    I'm not a compiler writer, so maybe this is all too difficult to do, but
    it seems like from the programmer's perspective things would be much
    easier if you could initialize allocatable entites to have an allocated
    state, possibly with values, if you could allocate() an entity that is
    already allocated (perhaps by specifying an optional keyword to allow
    the prior deallocation), if you could deallocate() an entity that is
    already deallocated, and if you could control the lower bounds of
    allocatable arrays during allocate-on-assignment.

    As for never needing to deallocate an allocatable entity, there are many situations where that is necessary, in addition to reallocating arrays
    to have different sizes and/or bounds. The move_alloc() intrinsic is
    useful for the size change, but there is no efficient way to change the
    bounds of an allocatable array while leaving its extents the same in the various dimensions. That should be an operation that requires
    essentially no computational effort, but at present requires the
    unnecessary copying of array data.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Ron Shepard on Thu Feb 24 07:52:36 2022
    On Thursday, February 24, 2022 at 5:45:27 PM UTC+11, Ron Shepard wrote:
    On 2/23/22 6:14 AM, Edmondo Giovannozzi wrote:
    [...]
    Most of the time I use allocatable or allocatable component of a user defined type in a procedure where they are dummy arguments with intent(out) or local variables. So they are always unallocated at the beginning of the procedure. Adding the
    reallocation on assignment, I rarely need to check their allocation status or deallocate them.
    Yes, that was my point. They are always unallocated at the beginning
    because there is currently no way to declare them to be in an allocated state or an allocated state with values. If that were possible, then
    there are many situations where that would simplify the logic of the program.

    Also, with reallocation on assignment, you lose control of the ability
    to specify the lower bound of the array. You must use an allocate() statement for that, and the array in the allocate statement must be deallocated, otherwise it is an error. Similarlly, the array must be allocated if used in a deallocate statement, otherwise it is an error.
    So the current situation is an intertangled mess of conditions and constraints, all leading to a lot of complicated code logic.
    .
    Really? The code is linearly executed.
    .
    You can write:
    deallocate (x) ; allocate (x); x = 1
    If you're testing whether x is already allocated, you can put that on the same line too.
    .
    I'm not a compiler writer, so maybe this is all too difficult to do, but
    it seems like from the programmer's perspective things would be much
    easier if you could initialize allocatable entites to have an allocated state, possibly with values, if you could allocate() an entity that is already allocated (perhaps by specifying an optional keyword to allow
    the prior deallocation), if you could deallocate() an entity that is
    already deallocated, and if you could control the lower bounds of allocatable arrays during allocate-on-assignment.

    As for never needing to deallocate an allocatable entity, there are many situations where that is necessary, in addition to reallocating arrays
    to have different sizes and/or bounds. The move_alloc() intrinsic is
    useful for the size change, but there is no efficient way to change the bounds of an allocatable array while leaving its extents the same in the various dimensions. That should be an operation that requires
    essentially no computational effort, but at present requires the
    unnecessary copying of array data.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Ron Shepard on Fri Feb 25 22:46:24 2022
    On Wednesday, February 23, 2022 at 10:45:27 PM UTC-8, Ron Shepard wrote:

    (snip)

    I'm not a compiler writer, so maybe this is all too difficult to do, but
    it seems like from the programmer's perspective things would be much
    easier if you could initialize allocatable entites to have an allocated state, possibly with values, if you could allocate() an entity that is already allocated (perhaps by specifying an optional keyword to allow
    the prior deallocation), if you could deallocate() an entity that is
    already deallocated, and if you could control the lower bounds of
    allocatable arrays during allocate-on-assignment.

    Personally I think it is strange, but array expressions always have a lower bound of 1. Since allocate on assignment uses the bounds of the
    expression being assigned, the lower bound will always be 1.

    If you want a different lower bound, then you ALLOCATE it first.

    If you want to ALLOCATE already allocated arrays, or DEALLOCATE
    unallocated arrays, without any error message, then put STAT=
    on, and ignore the value.

    I suppose it would be slightly more convenient if you could put
    STAT= without a variable, showing that you were ignoring it, but
    otherwise just name your variable IGNORE. (Convieniently
    already an INTEGER!)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to All on Sat Feb 26 00:06:28 2022
    On Saturday, February 26, 2022 at 5:46:26 PM UTC+11, gah4 wrote:
    On Wednesday, February 23, 2022 at 10:45:27 PM UTC-8, Ron Shepard wrote:

    (snip)
    I'm not a compiler writer, so maybe this is all too difficult to do, but
    it seems like from the programmer's perspective things would be much
    easier if you could initialize allocatable entites to have an allocated state, possibly with values, if you could allocate() an entity that is already allocated (perhaps by specifying an optional keyword to allow
    the prior deallocation), if you could deallocate() an entity that is already deallocated, and if you could control the lower bounds of allocatable arrays during allocate-on-assignment.
    Personally I think it is strange, but array expressions always have a lower bound of 1. Since allocate on assignment uses the bounds of the
    expression being assigned, the lower bound will always be 1.

    If you want a different lower bound, then you ALLOCATE it first.

    If you want to ALLOCATE already allocated arrays, or DEALLOCATE
    unallocated arrays, without any error message, then put STAT=
    on, and ignore the value.

    I suppose it would be slightly more convenient if you could put
    STAT= without a variable, showing that you were ignoring it, but
    otherwise just name your variable IGNORE. (Convieniently
    already an INTEGER!)
    .
    Not with IMPLICIT NONE.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to Robin Vowels on Sat Feb 26 12:02:18 2022
    On 2/24/22 9:52 AM, Robin Vowels wrote:
    Also, with reallocation on assignment, you lose control of the ability
    to specify the lower bound of the array. You must use an allocate()
    statement for that, and the array in the allocate statement must be
    deallocated, otherwise it is an error. Similarlly, the array must be
    allocated if used in a deallocate statement, otherwise it is an error.
    So the current situation is an intertangled mess of conditions and
    constraints, all leading to a lot of complicated code logic.
    .
    Really? The code is linearly executed.
    .
    You can write:
    deallocate (x) ; allocate (x); x = 1
    If you're testing whether x is already allocated, you can put that on the same line too.

    Hmm?

    As I pointed out, the test for allocation is necessary prior to this
    sequence of statements, otherwise it is a run time error if x is already deallocated.

    If the scalar x is already allocated and is some intrinsic type, then
    this sequence is a very expensive way to do the simple assignment

    x = 1

    If x is an array, then there needs to be an upper and perhaps a lower
    bound specified. For a nondefault lower bound, this is one of the
    examples I gave where allocation on assignment is often inadequate.

    If x is a derived type, and you are using a defined assignment, then
    there is a lot of context missing.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to All on Sat Feb 26 13:41:21 2022
    On 2/26/22 12:46 AM, gah4 wrote:
    On Wednesday, February 23, 2022 at 10:45:27 PM UTC-8, Ron Shepard wrote:

    (snip)

    I'm not a compiler writer, so maybe this is all too difficult to do, but
    it seems like from the programmer's perspective things would be much
    easier if you could initialize allocatable entites to have an allocated
    state, possibly with values, if you could allocate() an entity that is
    already allocated (perhaps by specifying an optional keyword to allow
    the prior deallocation), if you could deallocate() an entity that is
    already deallocated, and if you could control the lower bounds of
    allocatable arrays during allocate-on-assignment.

    Personally I think it is strange, but array expressions always have a lower bound of 1. Since allocate on assignment uses the bounds of the
    expression being assigned, the lower bound will always be 1.

    Yes, here is a short program that demonstrates that. Try to predict what
    the printed values will be before running it. Programmers often miss one
    or more of the cases.

    program talloc
    implicit none
    integer :: i
    integer :: a(-1:1,-1:1)=reshape([(i,i=1,9)],[3,3])
    integer, allocatable :: b(:,:)
    write(*,*) 'lbound(a)=', lbound(a)
    b = a
    write(*,*) 'b=a; lbound(b)=', lbound(b)
    deallocate(b)
    b = a(:,:)
    write(*,*) 'b=a(:,:); lbound(b)=', lbound(b)
    b = a(:0,:0)
    write(*,*) 'b=a(:0,:0); lbound(b)=', lbound(b)
    b = a
    write(*,*) 'b=a; lbound(b)=', lbound(b)
    b = a(:,:)
    write(*,*) 'b=a(:,:); lbound(b)=', lbound(b)
    b = a(0:,0:)
    write(*,*) 'b=a(0:,0:); lbound(b)=', lbound(b)
    b = a(:,:)
    write(*,*) 'b=a(:,:); lbound(b)=', lbound(b)
    b = a
    write(*,*) 'b=a; lbound(b)=', lbound(b)
    end program talloc

    If you want nondefault lower bounds, then an explicit allocate()
    statement is often required. Not always, but often.

    Also, it is not clear to me if that last case is fully specified by the standard. The wording in the standard needs to be more explicit to cover
    that case.

    If you want to ALLOCATE already allocated arrays, or DEALLOCATE
    unallocated arrays, without any error message, then put STAT=
    on, and ignore the value.

    This had not occurred to me. I guess a potential problem might be if the allocation failed for some other reason, then that failure would be
    obscured by this trick.

    The ability to deallocate() a deallocated array would be useful in cases
    where a whole group of arrays is being deallocated, but the prior
    allocation status of each array is unknown due to the preceding program
    logic.

    dealloocate( a, b, c, d, e, f, g, h ...)

    Currently the programmer must test and deallocate each one of them individually. It would be clearer, and less prone to errors, to simply
    allow the single deallocate() statement.

    The same consideration would apply to allocate() for several work arrays
    each with unknown prior allocation status. In this case, I think the appropriate semantics would be to conditionally allocate each array,
    first checking both its allocation status and also its currently
    allocated lower and upper bounds. In the latter case, if the extents
    match, but the bounds differ, then only the bounds should be changed,
    avoiding the potentially expensive allocation process and also
    preserving the content. Currently, there is no efficient way to change
    the bounds of an allocated array while keeping its contents intact, or
    keeping pointers to that target array defined while changing its bounds.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robin Vowels@21:1/5 to Ron Shepard on Sat Feb 26 11:49:30 2022
    On Sunday, February 27, 2022 at 5:02:24 AM UTC+11, Ron Shepard wrote:
    On 2/24/22 9:52 AM, Robin Vowels wrote:
    Also, with reallocation on assignment, you lose control of the ability
    to specify the lower bound of the array. You must use an allocate()
    statement for that, and the array in the allocate statement must be
    deallocated, otherwise it is an error. Similarlly, the array must be
    allocated if used in a deallocate statement, otherwise it is an error.
    So the current situation is an intertangled mess of conditions and
    constraints, all leading to a lot of complicated code logic.
    .
    Really? The code is linearly executed.
    .
    You can write:
    deallocate (x) ; allocate (x); x = 1
    If you're testing whether x is already allocated, you can put that on the same line too.
    Hmm?

    As I pointed out, the test for allocation is necessary prior to this
    sequence of statements,
    .
    Try
    if (allocated(x)) deallocate (x); allocate (x); x = 1
    .
    I was merely pointing out that it does not require
    " an intertangled mess of conditions and
    " constraints, all leading to a lot of complicated code logic."
    .
    BTW, no run-time error can occur when the ERRMSG option is used,
    .
    If the scalar x
    .
    x is an array, not a scalar.
    .
    is already allocated and is some intrinsic type, then
    this sequence is a very expensive way to do the simple assignment
    .
    if scalar x is already allocated, you just write an assignment statement.
    Try x = 1
    .
    x = 1

    If x is an array, then there needs to be an upper and perhaps a lower
    bound specified.
    .
    Not necessarily.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to All on Sat Feb 26 21:03:28 2022
    On Saturday, February 26, 2022 at 11:41:28 AM UTC-8, Ron Shepard wrote:

    (snip, I wrote)

    Personally I think it is strange, but array expressions always have a lower bound of 1. Since allocate on assignment uses the bounds of the
    expression being assigned, the lower bound will always be 1.

    Yes, here is a short program that demonstrates that. Try to predict what
    the printed values will be before running it. Programmers often miss one
    or more of the cases.

    Yes. Exactly why it is strange. If programmers miss it, it can easily cause problems.

    For one, I thing you should have to ask for reallocatability.
    That would have been easy with a REALLOCATABLE attribute, but
    we didn't get that one. With the current way, if you aren't careful,
    you could accidentally get reallocated, when not expecting it.

    Though R has one that is worse. In (some cases) a 2D array with one of
    the dimensions 1, is treated as a 1D array. If you don't expect it, lots of strange things happen.

    It is, on the other hand, convenient when mixing different bounds.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Ron Shepard on Sat Feb 26 21:14:22 2022
    On Saturday, February 26, 2022 at 11:41:28 AM UTC-8, Ron Shepard wrote:

    (snip)

    The same consideration would apply to allocate() for several work arrays
    each with unknown prior allocation status. In this case, I think the appropriate semantics would be to conditionally allocate each array,
    first checking both its allocation status and also its currently
    allocated lower and upper bounds. In the latter case, if the extents
    match, but the bounds differ, then only the bounds should be changed, avoiding the potentially expensive allocation process and also
    preserving the content. Currently, there is no efficient way to change
    the bounds of an allocated array while keeping its contents intact, or keeping pointers to that target array defined while changing its bounds.

    Well, changing the size is twice as efficient (or half as inefficient) as
    it used to be before MOVE_ALLOC.

    Before MOVE_ALLOC, you make a copy, reallocate the array,
    and copy back. Now you allocate, copy, and MOVE_ALLOC,
    so only one copy.

    C's realloc() can avoid the copy if the array is at the end of memory,
    (or, I suppose, the size decreases). There is, however, no way in C to
    know if it is reallocated in place or not.

    My programs that reallocate, C or Fortran, increase by 5/3 each time.
    The number of reallocations and copies is, then, log(size), and so
    not so large. If you increase linearly, then it is O(n) copies, and
    O(n**2) time. Don't do that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to Robin Vowels on Sun Feb 27 00:32:58 2022
    On 2/26/22 1:49 PM, Robin Vowels wrote:
    [...]

    Try
    if (allocated(x)) deallocate (x); allocate (x); x = 1
    [...]
    if scalar x is already allocated, you just write an assignment statement.
    Try x = 1

    Yes, that was my point. Why do all that complicated memory stuff in your
    above example when just the simple assignment works.

    If x is an array, then there needs to be an upper and perhaps a lower
    bound specified.
    .
    Not necessarily.

    How so?

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Thomas Koenig on Thu Mar 3 15:53:26 2022
    On Thursday, February 17, 2022 at 11:27:34 PM UTC-8, Thomas Koenig wrote:

    (snip)

    Can you explain this a little more, maybe with a (one or two line) example?

    module foo
    integer :: n ! This is a module variable
    contains
    subroutine bar
    integer :: j ! This is not a module variable
    end subroutine bar
    end module

    But how about SUBMODULE, which I don't see any examples of in the standard.

    If you put a module or submodule inside subroutine bar, then how does it work?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Arjan@21:1/5 to All on Fri Mar 4 07:19:14 2022
    Now that we are talking initialization: I would like to have the PASCAL feature that all modules (units) can have their own initialization routine that is run once the module (unit) is loaded, in order of dependence of the modules. Now I have to do these
    tasks explicitly for all modules in all my main programs, which is boring and not compact. Any chance that this will be adopted in FORTRAN?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steve Lionel@21:1/5 to All on Fri Mar 4 11:35:57 2022
    On 3/3/2022 6:53 PM, gah4 wrote:
    But how about SUBMODULE, which I don't see any examples of in the standard.

    If you put a module or submodule inside subroutine bar, then how does it work?

    You cannot put a module or submodule inside a procedure. A submodule
    doesn't go inside anything - it is "alongside" a module.

    --
    Steve Lionel
    ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
    Retired Intel Fortran developer/support
    Email: firstname at firstnamelastname dot com
    Twitter: @DoctorFortran
    LinkedIn: https://www.linkedin.com/in/stevelionel
    Blog: https://stevelionel.com/drfortran
    WG5: https://wg5-fortran.org

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