# Modern Fortran sample code

**URL:** <https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019>\
**Category:** Help\
**Created:** [October 6, 2021, 9:24pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019 "2021-10-06T21:24:49Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [October 6, 2021, 9:24pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/1 "2021-10-06T21:24:49Z")

</div>

If you had to write 10-12 lines of code (excl. declarations) showing the strengths and diversity of Modern Fortran to a newbie, what could that be? Not necessarily solving any real problem, just showing the capabilities of the language.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [October 6, 2021, 11:17pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/2 "2021-10-06T23:17:01Z")

</div>

@Arjen [has shown](http://flibs.sourceforge.net/qsort_reals.f90) how to use recursion and the array functionality of Fortran (`pack`, array sections, vectorized comparisons) to write quicksort very concisely. Here is a lightly modified code of his, with a driver.

```auto
module qsort_mod
implicit none
contains
pure recursive function qsort(data) result(sorted)
real, intent(in) :: data(:)
real :: sorted(size(data))
if (size(data) > 1) then
   sorted = [qsort(pack(data(2:),data(2:)<data(1))), data(1), &
             qsort(pack(data(2:),data(2:)>=data(1)))]
else
   sorted = data
end if
end function qsort
end module qsort_mod
!
program main
use qsort_mod, only: qsort
implicit none
real :: x(10)
call random_seed()
call random_number(x)
write (*,"(a10,*(1x,f0.3))") "initial",x
write (*,"(a10,*(1x,f0.3))") "sorted",qsort(x)
end program main

```

sample output:

```auto
   initial .869 .394 .228 .657 .793 .416 .494 .657 .851 .471
    sorted .228 .394 .416 .471 .494 .657 .657 .793 .851 .869

```

Edit: With the [newly approved conditional expressions](https://j3-fortran.org/doc/year/21/21-157r2.txt), the body of the function can be just one line:

```auto
sorted = (size(data) > 1 ? &
      sorted = [qsort(pack(data(2:),data(2:)<data(1))), data(1), &
                qsort(pack(data(2:),data(2:)>=data(1)))] : & 
      data )

```

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [October 7, 2021, 3:04am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/3 "2021-10-07T03:04:04Z")

</div>

> [@Beliavsky](#):
>
> … With the [newly approved conditional expressions](https://j3-fortran.org/doc/year/21/21-157r2.txt), the body of the function can be just one line:
> 
> ```auto
> sorted = (size(data) > 1 ? &
> sorted = [qsort(pack(data(2:),data(2:)<data(1))), data(1), &
> qsort(pack(data(2:),data(2:)>=data(1)))] : & 
> data )
> 
> ```

You mean

```Fortran
sorted = (size(data) > 1 ? &
! if size(data) > 1 condition is true
   [qsort(pack(data(2:),data(2:)<data(1))), data(1), &
       qsort(pack(data(2:),data(2:)>=data(1)))] : &
! or else
    data )

```

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [October 7, 2021, 4:53am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/4 "2021-10-07T04:53:46Z")

</div>

> [@msz59](#):
>
> If you had to write 10-12 lines of code (excl. declarations) showing the strengths and diversity of Modern Fortran to a newbie, what could that be? Not necessarily solving any real problem, just showing the capabilities of the language.

Well, if one wanted to simply show the strength and **diversity** of modern Fortran, especially in terms of Fortran being an evolving multiparadigm language with focus on numerical computing and performance, a silly illustrator can also be as follows, it’s not as short as you seek but not all that long either:

```Fortran
module m
   type :: numseq_t(n)
      integer, len :: n = 3
      integer :: vals(n)
   contains
      procedure, pass(this) :: calc => calc_seq
   end type
contains
   elemental subroutine calc_seq( this )
      class(numseq_t(n=*)), intent(inout) :: this
      integer :: i, lb, ub
      lb = (this_image()-1)*size(this%vals) ; ub = lb + size(this%vals) - 1
      this%vals = fibonacci_number( [( i, i = lb, ub )] )
   end subroutine
   elemental integer function fibonacci_number( n ) result(num)
      integer, intent(in) :: n
      select case ( n ) 
         case ( 0:1 )
            num = n
         case default
            num = fibonacci_number(n-1) + fibonacci_number(n-2) 
      end select
   end function
end module
   use m, only : numseq_t
   type(numseq_t(n=5)) :: numseq[*]
   integer :: i 
   call numseq%calc()
   sync all
   if ( this_image() == 1 ) then
      do i = 1, num_images()
         write( *, fmt="(*(g0,1x))", advance="no" ) numseq[i]%vals
      end do
   end if
end

```

You will notice the example builds on recent newbie discussions on this forum with

- **recursion** to determine a number sequence, the Fibonacci series here,
- the use of **structured programming** in program flow,
- **modular programming** with auto-generated **explicit interfaces** to procedures,
- the use of explicit **INTENT** s with procedure parameters,
- along with **functional programming** aspects to process arrays elementally,
- it combines that with **object-oriented design** to establish a “store” of number sequences,
- it hints at **templated programming** via a parameterized type for the store, and
- it employs **parallel programming** toward the calculations to stock that store of sequences

So you can see there is a lot going on in there that touches upon many of the facilities now available in Fortran.

Here’s the expected output using one processor that outputs the first 40 elements (5 per parallel compute image times 8 images) in the Fibonacci sequence:

> C:\Temp\>ifort /standard-semantics /Qcoarray:shared /Qcoarray-num-images=8 e.f90  
> Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.3.0 Build 20210609\_000000  
> Copyright (C) 1985-2021 Intel Corporation. All rights reserved.
> 
> Microsoft (R) Incremental Linker Version 14.29.30038.1  
> Copyright (C) Microsoft Corporation. All rights reserved.
> 
> -out:e.exe  
> -subsystem:console  
> e.obj
> 
> C:\Temp\>e.exe  
> 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [October 7, 2021, 5:06pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/5 "2021-10-07T17:06:01Z")

</div>

Thanks a lot for great samples! @FortranFan, could you please remind me what does `len` in  
`integer, len :: n = 5` mean? My memory seems to have a hole at this very place 🙂

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [October 7, 2021, 5:26pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/6 "2021-10-07T17:26:18Z")

</div>

> [@msz59](#):
>
> @FortranFan, could you please remind me what does `len` in  
> `integer, len :: n = 5` mean? My memory seems to have a hole at this very place

It refers to the `length-type parameter` of a parameterized type. It has some similarity in terms of semantics and syntax with length of a CHARACTER intrinsic type as in `character(len=` and how one works with that parameter. The use of such types can help to some degree with “genericization” of one’s methods (procedures) e.g., a subroutine that can reverse any string, or as shown above, filling a store of number sequences of any length.

The standard document itself, or **“Modern Fortran Explained”** , or some of the vendor language reference [**sites**](https://www.ibm.com/docs/en/xl-fortran-aix/16.1.0?topic=types-derived-type-parameters-fortran-2003) are good places to peruse if you want to look up further.

---

<div class="post-metadata">

**Author:** ![Federchen](https://avatars.discourse-cdn.com/v4/letter/f/ce7236/32.png) [@Federchen](https://fortran-lang.discourse.group/u/Federchen)\
**Post date:** [October 7, 2021, 7:22pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/7 "2021-10-07T19:22:12Z")

</div>

Only a code snippet though, but it’s taken from my today’s prototyping, coarray (runtime) parallel code as well. Spin-wait loops are usually inside synchronization routines; here it’s taken to the parallel logic codes to allow the programmer to do some calculation there instead of leaving the coarray image just idle waiting for the synchronization to complete.  
Naming conventions are a matter of taste, but Fortran makes it easy to implement features with very few lines of code and keep things readable, I would say.

```auto
! *****
  case (Enum_ImageType % ControlImage) ! on the control image
    control_FinishedFragmentedMethod: block
      integer(OOOGglob_kint), dimension (1:intNumberOfExecutingImages, 1:2) :: intA_ExecutingImageAndFMValue
      integer(OOOGglob_kint) :: intNumberOfSuccessfulRemoteNotifys
      !
      ! wait until all the execute images do signal that they are in state FinishedFragmentedMethod:
      spin_wait: do
        ! ********* local abort timer (time limit) for the spin-wait loop:
        call system_clock(count = intTime2); reaTimeShift = real(intTime2-intTime1) / reaCountRate
        if (reaTimeShift > reaTimeLimitInSec) logNotifyFailure = .true. ! time limit exceeded
        ! *********
        if (nofy_SyncFragmentedMethod % IsNotifyWait (intFragmentedMethodNotifyStatus, &
            intNumberOfExecutingImages, intA_ExecutingImageNumbers, &
            intNumberOfSuccessfulRemoteNotifys = intNumberOfSuccessfulRemoteNotifys, &
            intA_RemoteImageAndItsScalarIntegerValueToTransfer = intA_ExecutingImageAndFMValue, &
            logNoSpinWaitLoop = .true.)) then
          ! IsNotifyWait was successfull, no further action is required
        else ! the IsNotifyWait did fail
          logNotifyFailure = .true.
        end if
        if (intNumberOfSuccessfulRemoteNotifys == intNumberOfExecutingImages) exit spin_wait ! successfull
        if (logNotifyFailure) exit spin_wait ! non-successfull
      end do spin_wait
      !
      write(*,*) '==============================================================================='
      write(*,*) 'On the contol image, the newly collected and now adjusted FMValues: ', intA_ExecutingImageAndFMValue(:,2)
      write(*,*) '==============================================================================='
      write(*,*) 'Number Of Successful Remote Notifys: ', intNumberOfSuccessfulRemoteNotifys
      !
      if (logNotifyFailure) return ! non-successfull
    end block control_FinishedFragmentedMethod
  ! *****
  end select finished_fragmented_method

```

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [October 7, 2021, 10:33pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/8 "2021-10-07T22:33:48Z")

</div>

> [@FortranFan](#):
>
> The standard document itself, or **“Modern Fortran Explained”** , or some of the vendor language reference [**sites**](https://www.ibm.com/docs/en/xl-fortran-aix/16.1.0?topic=types-derived-type-parameters-fortran-2003) are good places to peruse if you want to look up further.

Thanks a lot for refreshing my memory, indeed PDTs come with `len` or `kind` attributes to type parameters. Following your advise I checked MFE and, incidentally, found an erroneous code snippet there, namely Figure 13.2 on p. 282:

```auto
  type character_with_max_length(maxlen, kind)
    integer, len :: maxlen
    integer, kind :: kind = selected_char_kind('default')
    integer :: length = 0
    character(kind) :: value(maxlen) ! ERROR 1
  end type

  type(character_with_max_length(100)) :: name

  name = character_with_max_length(100)('John Hancock') ! ERROR 2

```

1 - as is, it defines `value` to be a `maxlen`-elements array of characters instead of a character object of len=maxlen; it should probably read `character(maxlen, kind) :: value`  
2 - this error is reported by **ifort** ; , `'John Hancock'` is interpreted (positionally) as value for `length` component and thus the component `value` is not set (though it should be, as there is no default given). To fix it, one can add explicit component name: `(value='John Hancock')`  
With ERROR 2 fixed, ERROR 1 shows only in runtime, segfaulting the program (ifort version 2021.3.0 on Ubuntu 20.04), though I am not quite sure why. Outside of type constructor, an array of characters may be assigned with a longer string, resulting in all elements of the array being set to ‘J’. Probably inside the constructor, the type compatibility requirements are stricter. But if it is really so, it should probably be reported during compile time (?)

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [October 7, 2021, 11:37pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/9 "2021-10-07T23:37:01Z")

</div>

> [@msz59](#):
>
> … found an erroneous code snippet there, namely Figure 13.2 on p. 282: …

Attn: @m_b_metcalf , perhaps you and/your coauthors can explain to OP what is going on with Figure 13.2 in the book (8th Edition, 2018)?

---

<div class="post-metadata">

**Author:** ![m\_b\_metcalf](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@m\_b\_metcalf](https://fortran-lang.discourse.group/u/m_b_metcalf)\
**Post date:** [October 9, 2021, 9:37am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/10 "2021-10-09T09:37:24Z")

</div>

I will, but only when I return home. Thanks for drawing this to our attention.

Mike Metcalf

---

<div class="post-metadata">

**Author:** ![m\_b\_metcalf](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@m\_b\_metcalf](https://fortran-lang.discourse.group/u/m_b_metcalf)\
**Post date:** [October 26, 2021, 8:17am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/11 "2021-10-26T08:17:32Z")

</div>

We now confirm that this Figure contains the two errors reported, and the corrections that were suggested will be incorporated into the next printing.

We are always grateful for readers’ comments.

Regards,

Mike Metcalf

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [October 26, 2021, 4:46pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/12 "2021-10-26T16:46:37Z")

</div>

Thanks @m_b_metcalf for confirming the errors and for responding here.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [October 26, 2021, 9:23pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/13 "2021-10-26T21:23:23Z")

</div>

> [@m\_b\_metcalf](#):
>
> We are always grateful for readers’ comments.

You’re welcome! It is a pleasure to be able to make a correction to such a great book.

---

<div class="post-metadata">

**Author:** ![Carltoffel](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/carltoffel/32/1680_2.png) [@Carltoffel](https://fortran-lang.discourse.group/u/Carltoffel)\
**Post date:** [January 27, 2023, 8:27am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/14 "2023-01-27T08:27:41Z")

</div>

Another example could be this short code to calculate the Mandelbrot set. Not as modern as some other examples, but pretty output.

```auto
program mandel
    implicit none
    integer, parameter :: N = 99 ! smaller than half of terminal width
    character(3) :: N_str
    complex :: c(N,N) ! coordinates
    complex :: z(N,N) ! values for iteration
    integer :: i, j
    c = 0.0
    z = 0.0
    do i = 1, N
        c(:, i) = c(:, i) + [(cmplx(3.*j/(N-1)-2, 0.),j=0,N-1)]
        c(i, :) = c(i, :) + [(cmplx(0., 3.*j/(N-1)-1.5),j=0,N-1)]
    end do
    do i = 1, 100
        z = z**2 + c
    end do
    write(N_str, "(i3)") N
    print "("//trim(N_str)//"(a))", merge('##', ' ', abs(z)<2)
end program mandel

```

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [January 27, 2023, 9:16am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/15 "2023-01-27T09:16:18Z")

</div>

> [@Carltoffel](#):
>
> `[(cmplx(3.*i/(N-1)-2, 0.),i=0,N-1)]`

Interesting solution!

I think it would be more readable if you replace `coords` by `c` and `values` by `z`.  
And replace the `i` in the brackets by `j` to avoid confusion for the reader.

---

<div class="post-metadata">

**Author:** ![Carltoffel](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/carltoffel/32/1680_2.png) [@Carltoffel](https://fortran-lang.discourse.group/u/Carltoffel)\
**Post date:** [January 27, 2023, 9:48am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/16 "2023-01-27T09:48:47Z")

</div>

Thank you for your feedback, I edited the code. For someone who is familiar with fractals (based on your profile picture I guess you are ^^), `z` and `c` might be familiar. But for those who are not, I tried to add comments. I’m not sure about the comment for `z`. Do you think `values for interation` is a good description?

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [January 27, 2023, 10:16am UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/17 "2023-01-27T10:16:32Z")

</div>

Great, we should stick to the mathematical notations (FORmula TRANslator ) and terms. I am not the most familiar with the English mathematical vocabulary, but I would say that `z(N,N)` stores for each point of the complex plane the last computed term of the series z\_n = z\_{n-1}^2 +c

[https://en.wikipedia.org/wiki/Series\_(mathematics)](https://en.wikipedia.org/wiki/Series_(mathematics))

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [January 27, 2023, 1:42pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/18 "2023-01-27T13:42:23Z")

</div>

I know there are mixed feelings about it, but long descriptive names make the code more readable in some regions, but then become ugly in dense formulas. ASSOCIATE lets you  
have the best of both worlds; and is a “modern” feature that might be demonstrated here.

```fortran
program mandel
    implicit none
    integer, parameter :: N = 99 ! smaller than half of terminal width
    character(3) :: N_str
    complex :: coordinates(N,N) 
    complex :: values_for_iteration(N,N)
    integer :: i, j
    coordinates = 0.0
    values_for_iteration = 0.0

    associate(z=>values_for_iteration,c=>coordinates)
     do i = 1, N
         c(:, i) = c(:, i) + [( cmplx(3.0* j / (N-1) - 2, 0.), j=0,N-1)]
         c(i, :) = c(i, :) + [( cmplx(0.0, 3.0*j / (N-1) - 1.5),j =0,N-1)]
     end do
     do i = 1, 100
         z = z**2 + c
     end do
    end associate

    write(N_str, "(i3)") N
    print "("//trim(N_str)//"(a))", merge('##', ' ', abs(values_for_iteration)<2)
end program mandel

```

---

<div class="post-metadata">

**Author:** ![Carltoffel](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/carltoffel/32/1680_2.png) [@Carltoffel](https://fortran-lang.discourse.group/u/Carltoffel)\
**Post date:** [January 27, 2023, 4:22pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/19 "2023-01-27T16:22:31Z")

</div>

Nice idea!

> [@urbanjost](#):
>
> ```auto
> write(N_str, "(i3)") N
> end associate
> 
> ```

I would swap those lines because `write` doesn’t need to be in there, and it is more closely related to the `print`-statement.

Another approach is to use short letters as I did, and then comment the variables with double `!!`. Then, when you are using [`fortls`](https://fortls.fortran-lang.org/index.html), the editor will give you a hint, whenever your cursor is on `z` or `c`.

PS: I tried to use `where` in the main loop to avoid iterating over hundreds of `NaN`s, but it made the code significantly slower.

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [January 27, 2023, 5:22pm UTC](https://fortran-lang.discourse.group/t/modern-fortran-sample-code/2019/20 "2023-01-27T17:22:37Z")

</div>

I moved the WRITE. I was slow to come around to using ASSOCIATE or long names, possibly because of habit (in hand calcs short abbreviations and symbols are ubiquitious); and FORTRAN only allowed for short names as well; so I was very comfortable with very short names. I have come around to preferring longer names in general in computer code but they could make complex formulas very cluttered, and then along came ASSOCIATE (which I admit had a confusing double use that made me avoid it at first). I gradually find I use it more and more; as it has the advantage that the compiler “checks” the use, whereas a comment is ignored in compilation and so I find comments more prone to error. It really varies from case to case for me; but since the topic was modern Fortran I thought this nice compact example was a good place to demonstrate it.

I would comment and/or name the “100” though. It is truly a “magic number” which I prefer to move to the declarations; and is also probably the most fun number to play with in the algorithm  
anyway, which is easy to miss when it is “just a number”.

I would not have thought the WHERE would have been much different in performance and would have been another newer feature to demonstrate but I tried it after seeing your comment and saw a significant slowdown in big iterations too. Interesting.

It would be nice if fortls did the same thing with ASSOCIATE it does with the !!. It would be cool if in the editor you could toggle between long and short names but that is probably not trivial to implement.
