What is the most convenient way to create a matrix with given elements?

Dear all,

This must be a very dumb question.
When I read a matlab code, just say, a simple 2 by 2 matrix A, it can be written as

A = [1 2; 3 4] 

Now in Fortran, do I have to things like below?

reshape( [1, 3, 2, 4], [2,2]   )

I know I can always use reshape, but, is there more direct and convenient way to construct a Matrix?

I am asking this because in the new Fortran standard, we can already construct 1D array like

B = [1, 2, 3, 4, 5] 

It is already very similar with python/julia/matlab.
It makes me think that perhaps modern Fortran can also construct 2D matrix like python/julia/matlab?

Thank you very much in advance!

2 Likes

I think reshape is the only intrinsic possibility. But it is not too difficult to use with a bit of elegant writing, like,

integer(IK) , parameter     :: nd = 3_IK, np = 5_IK
real(RK)    , parameter     :: Sample(nd,np) =  reshape([ 0.706046088019609031832846377421_RK, 0.031832846377421276922984960890_RK, 0.276922984960890706046088019609_RK &
                                                        , 0.046171390631154097131781235848_RK, 0.097131781235848823457828327293_RK, 0.823457828327293046171390631154_RK &
                                                        , 0.694828622975817317099480060861_RK, 0.317099480060861950222048838355_RK, 0.950222048838355694828622975817_RK &
                                                        , 0.034446080502909438744359656398_RK, 0.438744359656398381558457093008_RK, 0.381558457093008034446080502909_RK &
                                                        , 0.765516788149002795199901137063_RK, 0.795199901137063186872604554379_RK, 0.186872604554379765516788149002_RK &
                                                        ], shape = shape(Sample))

Just pay attention to the column-wise ordering of the elements when reshape occurs. If you like the lines of the code to truly represent the rows of the matrix, you can simply apply the transpose intrinsic to the reshaped matrix,

! A lower triangle matrix.
real(RK)    , parameter :: MatLow(nd,nd) = transpose(reshape(   [ 1.00_RK,                 0._RK,                0._RK &
                                                                , 0.25_RK, +1.391941090707505_RK,                0._RK &
                                                                , 1.00_RK, -0.538815906080325_RK, 1.307546335452338_RK ], shape = shape(MatLow)))

2 Likes

Unfortunately I think reshape is the only way as @shahmoradi said. However, I wish Fortran allowed the Matlab style matrix input. See this proposal:

4 Likes

Thank you very much @shahmoradi @certik !
Great solutions!

Perhaps, besides reshape trick, a way kind of like matlab is to input the matrix row by row, like below,

A(1,:) = [1,2] 
A(2,:) = [3,4]

By the way, I suddenly remember somewhere perhaps in Dr. Fortran’s @sblionel youtube video,

I realized that the symbol ; can be used in Fortran, so, in one line, it can be,

A(1,:) = [1,2]; A(2,:) = [3,4]
2 Likes

This Matlab syntax is awful. It’s kind of convenient, but it shows all the worst parts about how matlab treats everything as a matrix and has really weird semantics around assignment. @certik while you’re looking at matrix literals, it might be a good idea to consider n dimensional array literals. Julia added these as of 1.6, and they are pretty nice. We use the rule of n semi-colons indicates a new “row” in the nth dimension. For example

A = [1 2 3
        4 5 6
       ;;;
        7 8 9
        0 1 2]

produces a 2x3x2 array. This is nice for people working in higher dimensions (largely physicists).

3 Likes