Printing a matrix of unknown size to file preserving the shape

Hi !
Can somebody please tell me how to print a matrix of unknown size to file as it is. How to set the format statement? Is there a way to parameterize format statement using Lbound and Ubound ?
For example 2 x 3 matrix
2 3 4
3 4 5
should be printed as it is to the console or file.

Thanks.

What do you mean by “as it is”? On pencil and paper? Bits in IEEE floating point format in the computer? A hexadecimal string representation thereof?

If you mean formatted output on a computer display, in decimal notation, for matrices of modest size, this can be done. Many numerical libraries such as NAG and IMSL provide subroutines for this purpose.

Sorry of the ambiguity.
By “as it is” I mean in decimal notation. Like if the matrix in the memory is 2 x 3, if we print normally it will come out in a column straight line.
for example:
2 3 4
3 4 5
will come as
2
3
3
4
4
5
But if I don’t know the size (i.e 2 x 3), but when I print it - I should be able to see:
2 3 4
3 4 5
in the file.

I think this program does what you want, in two ways, although the second does assume you know how many columns the matrix has.

program main
implicit none
integer, parameter :: n1 = 2, n2 = 3
integer            :: i,mat(n1,n2)
mat(1,:) = [2,3,4]
mat(2,:) = [3,4,5]
do i=1,n1
   write (*,"(*(1x,i6))") mat(i,:) ! unlimited format used, with 6 positions for each integer, separated by a space
end do
write (*,"(3(1x,i6))") transpose(mat) ! Alternative using format reversion. Transpose used because Fortran arrays are column major.
end program main

Output:

      2      3      4
      3      4      5
      2      3      4
      3      4      5
2 Likes

If you don’t know the size, what you print would likely be a false representation.

If you have six elements (and you know that you have six), the matrix could be (6 X 1), (3 X 2), (2 X 3) or (1 X 6). You could have used some storage scheme other than “dense storage”.

1 Like

Thanks @Beliavsky

The Fortran WIki discussion on this
shows a generic example for INTEGER values, and references a library that handles this in a very general way via the DISP(3f) procedure

Kristjan Jonasson, Department of Computer Science, 
School of Science and Engineering, University of Iceland, 
Hjardarhaga 4, 107 Reykjavik, Iceland (jonasson@hi.is).

that is available on-line in several formats and probably handles any way you want to print small matrices in row-column order. It was also an ACM article.

There are several github clones of the library. If you are an fpm(1) user I have a clone of that set up for fpm(1) I think I could add to github in a few minutes (have to re-read the licensing to make sure).

2 Likes

Thanks @urbanjost. That would be a great help

Here is one that avoids temporary arrays and transpose(),

integer :: i, j
real :: Matrix(5,3) = transpose(reshape([( real(i), i = 1, 15 )], shape = [3,5]))
write(*,"(*(g0))") ((Matrix(i,j), ", ", j = 1, 3), new_line("a"), i = 1, 5)
end
1.00000000, 2.00000000, 3.00000000, 
4.00000000, 5.00000000, 6.00000000, 
7.00000000, 8.00000000, 9.00000000, 
10.0000000, 11.0000000, 12.0000000, 
13.0000000, 14.0000000, 15.0000000, 

UPDATE: I think I missed an important part of your question: Matrix of unknown size/shape. The above solution assumes a known shape.

1 Like

OK; so add these two lines to your fpm.toml file:

[dependencies]
M_display        = { git = "https://github.com/urbanjost/M_display.git" }

put this program into app/confidence_test.f90 in your fpm project directory to give it a quick test drive:

program demo_M_display
use M_display
implicit none
integer, parameter :: rk = selected_real_kind(6), n = 3
real(rk) :: a(n,n), b(n,n), x
integer i, j, k(5)
   forall(i=1:n, j=1:n)
      a(i,j) = exp(real(i+j-1, rk))
      b(i,j) = exp(real(i**j, rk))
   end forall

   call disp_set(advance = 'double')
   call disp('A = ', a)
   call disp(b)
   call disp(a(1:2,:),'f0.5')
   call disp('MATRIX', a, style='UNDERLINE & NUMBER', unit=-3, digmax=4)
end program demo_M_display

and enter

fpm run confidence_test --profile release --compiler gfortran

And you should get just about any form of matrix output
you can think of, like:

A =  2.718   7.389   20.086
     7.389  20.086   54.598
    20.086  54.598  148.413

2.71828E+00  2.71828E+00  2.71828E+00
7.38906E+00  5.45981E+01  2.98096E+03
2.00855E+01  8.10308E+03  5.32048E+11

2.71828   7.38906  20.08554
7.38906  20.08554  54.59815

       MATRIX       
--------------------
     1     2      3 
1   2.7   7.4   20.1
2   7.4  20.1   54.6
3  20.1  54.6  148.4

and you can get rid of the confidence_test.f90 file and just add the “use M_display” and the call(s) to disp(3f) into your code optionally selecting the options you want and that should do it.
I need to clean up the github repository and add more of the original author’s examples and such but that will let you try it.

PS: The documentation is on M_display already. There is a lot of documentation but for basic use you just “call disp(array)”.

5 Likes

Thank you. This is what I am exactly looking for.

No prob. Been meaning to do some fpm(1) wrappings of some other Open Source packages anyway. The more the merrier. I am hoping others will find this useful as well. I would like to merge some other routines with this so one can flip a switch and get the output as a table in CSV, HTML, a few markdown varients, LaTex, … as well. One of these days …

1 Like