1

I am trying to translate matlab/gnu octave code into gfortran language code.

I have done declaration of struc to form an array as it is written in matlab. However the compiler will not process the SIZE command due to that array issue that I do not understand. Below is the octave code I am trying to translate

function test1
clc;
close all;
start= 5;
function out = function1(start)
myarray = struct(...
    'list1', {'A', 'Cc', 'B', 'E', 'F', 'G', 'H', 'I'}, ...
    'list2', {1, 2,  3,  4, 5, 6, 7, 8},...
    'list3', {3, 3, 3, 3, 3, 2, 2, 2});
function list1 = function2(list2)
    done = false;
    myarray    
    numel(myarray)
    ra = randi([1 numel(myarray)], 1, 1)
    myarray(ra).list2;

    list1 = myarray(ra);
    if list1.list1 == 'E'
        list1.list1 = round(randn(1,1) * 5);
    end
   end
  x = {}; 
  y = [];
  list2 = 0;    
    list1 = function2(list2);
    list2 = list2 + list1.list3;
  out = struct('x', {x}, 'y', {y});
 end
function1(5)
end

The output of the octave code is,

test1

myarray =

1x8 struct array containing the fields:

list1
list2
list3

ans =  8
ra =  1
ans =

scalar structure containing the fields:

x = {}(0x0)
y = [](0x0) 

My gfortran code is,

function function1(start) result(out1)

 type myarray
 character, dimension(8)::list1=(/'A','C','B','E','F','G','H','I'/); 
 integer, dimension(8)::list2 =(/1,2,3,4,5,6,7,8/); 
 integer, dimension(8)::list3 =(/3,3,3,3,3,2,2/);
  end type 

  integer :: start;
  integer :: out1;
  integer :: sd;

 contains

  function function2(list2) result(list1)

   integer, intent(in) :: list2; ! input
   integer :: list1;             ! output  
   logical :: done;  
   integer, dimension(1,1) :: ra;
   real    :: rnd1;

    done = .FALSE.


    call random_number(rnd1);
    ra = nint(rnd1*5);
    sd= size(myarray);
   ! ra = nint(rnd1*size(myarray));
       print*, "random number is ", ra;
     myarray(ra)

 end function function2

 end function function1

program test1
use iso_fortran_env
implicit none

integer                 :: start, xout;
real                    :: ra;
integer                 :: function1;

start =5;
xout=function1(5);
end program test1

The error message I get from build command is:

gfortran  -Ofast -Wall -o "test1" "test1.f90"  
test1.f90:32:16:
      myarray(ra).list2;
            1
Error: Derived type ‘myarray’ cannot be used as a variable at (1)
test1.f90:29:17:
     sd= size(myarray);
             1
Error: ‘array’ argument of ‘size’ intrinsic at (1) must be an array
Compilation failed.

I believe the issue is my declaration of structure of the array. I am missing something there. Any suggestions? Note that in gfortran code in list1 values I had to change character 'Cc' into 'C' to make it work.

0

1 Answer 1

2

Unlike in the Matlab case, where struct creates an object with the given values, the type statement in Fortran doesn't.

Instead, type myarray defines what an object would look like. No object is created, and we need to do something like

type myarray
   ...   ! The definition of components
end type myarray
type(myarray) obj ! Declare an object of the defined type.

After this, obj is your object of interest.

However, there's more to note. With

type myarray
  character, dimension(8)::list1=(/'A','C','B','E','F','G','H','I'/); 
  integer, dimension(8)::list2 =(/1,2,3,4,5,6,7,8/); 
  integer, dimension(8)::list3 =(/3,3,3,3,3,2,2/);
end type 

you aren't (again) creating an object. When you do create an object (using type(myarray) obj, that object likely starts with those values specified. This isn't quite the same things as you may expect with the Matlab struct statement, though. You can read about default initialization and constructors for details of that.

Coming to size(myarray), an object declared solely as type(myarray) obj is a scalar object. This is the difference between "arrays of structures" and "structures of arrays". The "structure" myarray contains three arrays each of length 8. To instead have an array of structures:

type myarray
  character list1
  integer list2, list3
end type myarray
type(myarray), dimension(8) :: array

You will, however, have to construct the array. Perhaps

array = [myarray('A',1,3), myarray('C',2,3), ...]

Other question have answers which go in to details of constructing such arrays of structures.

Sign up to request clarification or add additional context in comments.

4 Comments

the command 'size' has nothing to do with "changing size". It has to do with determination of array size. The matlab numel means determine the dimension of the array which is 8. I think this is equivalent to "size" in gfortran.
Yes, I didn't write that part correctly. What I meant to write (and will edit), is that the derived type object you have in the Fortran code is scalar.
your example of array construction solved my problem. Although "Cc" cannot be used , I will see if I can solve that or get away with it. So what is the fortran equivalent for list1.list1 (in octave)?
If you mean myarray.list1 then array%list1. You should find such details in any (good) description of using Fortran's derived types.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.