# Data Structures

Modern Fortran enable data to be organized using collections and structured data. In this article you can learn how to define and manipulate data structures.

## Arrays

Arrays are multidimensional variables that contain more than one value where each value is accessed using one or more indices. First element along any dimension is at index 1 in contrast to C and Java where first element start from 0. Index can't have gaps.

### Declaration

You can declare arrays of any type but all elements in a single array must have the same type. There are three notations for declaring array variables:

1. You can use dimension attribute after type, separated by comma to specify 1 or N fix dimensions in paranthesis. This will reserve the space necesary for multiple elements.

``````
! 1D integer array of 9 elements
integer, dimension(9) :: array_nae

! 2D real array, we call it matrix
real, dimension(3, 3) :: matrix_name
``````

2. You can specify the number of values using round paranthesis after the variable name. This is more intuitive and not so verbose. Whatever method you use, the elements are not initialized.

``````
! An array of 9 real elements
real :: array_name(9)

! A matrix of 9 integer elements
integer :: matrix_name(3,3)
``````

3. You can specify lower and upper bounds for indexes. In special cases this could be useful. This method is rarely used by advanced developers to create custom index that start with other than 1, for example: a yearly schedule.

``````
! Custom lower and upper bounds
real :: zeroid_array(0:9)

! Negative index is also possible
real :: negid_array(-5:5)
``````

### Initialization

You can initialize all the values of one entire array in a single statement. Actually you should do this only if you do not use other method to give initial value to all elements.

#### Array literals

Array literal is enclosed in square brackets [...], literal values are separated by comma. The same notation is used for constructors to initialize the array. Notice that [] is not used for index, and array dimension but (). Very strange!

``````
! using array literal
real :: my_array(10) = [1,2,3,4,5,6,7,8,9,10]
``````

#### Array constructor

To avoid loops for Array initialization we can use a special expression that generate a series of nambers, called range. A range expression is enclosed in round brackets.

example: arrays.f95
``````!fortran example
program arrays
! 1D integer array
integer, dimension(3) :: A
integer i

! give value to all elements
A=[(i, i=1,3)]

! print all values
print "(3i4)", A(1:3)
end program
``````
console
``````~>./arrays
1   2   3
~>
``````

### Memory Model

In memory elements are organized linear, columns first. We say that matrix are in column major order, in contrast to C where row major order is used. It is important to use the right order when you travers a 2d array. Column Major Order

Nested loops can be used to access every element in the matrix. When you do this kind of loops, pay atention to order of indexes. In fortran you must use second index for outer loop and first index for inner loop. For large matrix this can improve performance.

example: matrix.f95
``````program matrix
! 2D integer array
integer, dimension(3, 3) :: M

! give value to all elements
do j=1,3
do i=1,3
M(i,j)=j*10+i
end do
end do
! output matrix elements
print "(3i4)", M ! 3 columns
print "(9i4)", M ! 9 columns
end program
``````
console
``````
>./matrix
11  12  13
21  22  23
31  32  33
11  12  13  21  22  23  31  32  33
``````

### Slicing

A powerful feature of the Fortran language is its built-in support for array operations. You can perform operations part of an array using array slicing notation: A(x:y) for array or M(x:y, a:b) for a matrix. Let's analyze the example:

example: slices.f95
``````!fortran example
program slices
implicit none

integer :: i, j
integer :: m(9, 9)

! Implied do loop constructor
do i=1,9
m(i,:)=[(j*10+i, j = 1, 9)]
end do
print "(9i4)", m

! Set value elements by range
m(:,:) = 0
m(1:5,1:5) = 1
m(6:,6:)   = 2
print *, repeat("_",36)
! Print new values
print "(9i4)", m
end program
``````
console
``````
~>./slices
11  12  13  14  15  16  17  18  19
21  22  23  24  25  26  27  28  29
31  32  33  34  35  36  37  38  39
41  42  43  44  45  46  47  48  49
51  52  53  54  55  56  57  58  59
61  62  63  64  65  66  67  68  69
71  72  73  74  75  76  77  78  79
81  82  83  84  85  86  87  88  89
91  92  93  94  95  96  97  98  99
__________________________________
1   1   1   1   1   0   0   0   0
1   1   1   1   1   0   0   0   0
1   1   1   1   1   0   0   0   0
1   1   1   1   1   0   0   0   0
1   1   1   1   1   0   0   0   0
0   0   0   0   0   2   2   2   2
0   0   0   0   0   2   2   2   2
0   0   0   0   0   2   2   2   2
0   0   0   0   0   2   2   2   2
``````

### Dynamic Arrays

Arrays can be defined resizable, then allocate memory later. You can use allocatable attribute in declaration and then allocate function to reserve the required memory.

example: dynamic.f95
``````
>program main
implicit none
! define dynamic arrays
integer, allocatable :: darray(:)
integer:: i = 0, d = 0 ! define the dimension
print *, "dimension:", read *, d
allocate(darray(d))  ! resize the arrays
darray = [(i,i=1,d)] ! using constructor

! create a dynamic format and print
print "("//trim(str(d))//"i4)" , darray
deallocate(darray)   ! remove from memory
contains
! "Convert an integer to string."
character(len=20) function str(k)
integer, intent(in) :: k
write (str, *) k
end function
end program
``````

## Strings

In Fortran, strings are defined using character type, follow (len) argument. An array can be defined as fixed size or allocatable. For allocatable strings you can allocate memory later after you can calculate the required capacity.

example: allocate.f95
``````
>program main
! declare two empty strings
character(len=5) :: string_one
character(len=:), allocatable:: string_two

! allocate memory for string two
allocate(character(6) :: string_two)

string_one = "first"
string_two = "second"

! concatenate and print
print *, string_one //" "// string_two
end program
``````

## Structures

Fortran has 5 built-in data types that can be used to define derived types. These are special form of data types that can encapsulate built-in types as well as other derived types.

#### Symple syntax

Most of the time a type has only a name and a group of variables called "attributes" or sometimes "fields". In Fortran the "derived types" are similar to "classes" you encounter in OOP languages.

``````
type :: identifier_name
! attributes
...
end type
``````

You can define more advanced data types. We try to show you many optional features by using square brackets []. However in next examples you will realize, square brackets are not actually part of syntax. It just show that a feature is optional.

``````
type ,attribute-list :: identifier_name [("parameter list")]
["parameterized definition"]
["private statements or sequence statements"]
["member variables (fields or attribute)"]
contains
["type bound subprograms"]
end type
``````

## Program Example

In this example we create 2 items. Each item is a variable declared from a derived type "wheel" and initialize the attributes using symbol "%". Notice this symbol is not modulo, like in C. For module we use built-in function mod() instead of "%".

example: wheels.f95
``````
program objects
character(len=*), parameter :: fmt = "(i3,i3,f6.2,' ',a,' ',a)"
! derived data type
type :: wheel
integer :: spokes, diameter
real :: width
character(len=4):: breaks
character(len=15) :: material
end type
! define and create two wheels
mountain = wheel(32, 24, 2.2, "disk", "steel")
! second weel attributes
! list the two weels with attributes
``````
{"ft_lang_label":"__label__en","ft_lang_prob":0.6521522,"math_prob":0.93160796,"size":7057,"snap":"2023-14-2023-23","text_gpt3_token_len":2043,"char_repetition_ratio":0.12037431,"word_repetition_ratio":0.0726257,"special_character_ratio":0.31939918,"punctuation_ratio":0.1673177,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.95788944,"pos_list":[0,1,2],"im_url_duplicate_count":[null,1,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-03-24T13:04:03Z\",\"WARC-Record-ID\":\"<urn:uuid:f05c3c5c-11ec-4a48-978d-739ad8f80e29>\",\"Content-Length\":\"13231\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:027eda8e-9657-479e-96ab-efb16a44e714>\",\"WARC-Concurrent-To\":\"<urn:uuid:9f73c8e3-191c-4228-99f6-c2f47d88388f>\",\"WARC-IP-Address\":\"104.193.142.74\",\"WARC-Target-URI\":\"http://sagecode.net/fortran/data.html\",\"WARC-Payload-Digest\":\"sha1:2KTYBZTAWTXGSUQWAUXXUQ2SETT7BZKM\",\"WARC-Block-Digest\":\"sha1:OSGQKLKLK4F6LDJ6E7GQA7ZCG5B3XEB2\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-14/CC-MAIN-2023-14_segments_1679296945282.33_warc_CC-MAIN-20230324113500-20230324143500-00606.warc.gz\"}"}