0

I have a problem :

problem

find maximum sum of values(Aij) of N columns

The function header should be

real*8 function Alnorm(A, M)
real*8 A(M, *)

So, I decided to do the following

program hw2

real*8 Arr(3, 4)
real*8 ans
integer :: i, j

read*, ((Arr(i,j), j=1,4), i=1,3)

ans = Alnorm(Arr, 3)
write(*, *) ans

stop
end program hw2

real*8 function Alnorm(A, M)
real*8 A(M, *), cur

Alnorm = 0.0
N = size(A, 2)

do i = 1, N
    cur = 0
    do j = 1, M
        cur = cur + A(j,i)
    enddo
    if(Alnorm < cur) then
        Alnorm = cur
    endif
enddo

return
end function Alnorm

However, I can't find size N.

'dim' argument of 'size' intrinsic at (1) is not a valid dimension index

I wanted to use the assumed shape array, but I had to use the assumed size array because of the conditions.

How can I solve this problem?

김승현
  • 19
  • 2
  • You could solve it by using standard Fortran, and avoiding methods that have been out of date for 30 years. Please look up assumed-shape arrays, interfaces and modules in your Fortran book. Also please look up kinds in Fortran, for instance at https://stackoverflow.com/questions/838310/fortran-90-kind-parameter, and stop using real*8 which is not and has never been part of Fortran. Also please stop nymshifting. – Ian Bush Sep 21 '20 at 09:45
  • 2
    I read it as not being able to use SIZE on an assumed size array... – Ian Bush Sep 21 '20 at 11:20
  • 1
    Well, as I wrote *The question is rather confusing ...* ! – High Performance Mark Sep 21 '20 at 12:01
  • Indeed ... I think a close vote due to lack of clarity may be the order of the day. – Ian Bush Sep 21 '20 at 12:25
  • 1
    Does your function have to be external? What are the actual constraints you were given? – Vladimir F Героям слава Sep 21 '20 at 17:13

2 Answers2

3

The subroutine A1norm is implemented using an assumed-size array (lbound:*). Assumed-size arrays have no bounds in its last dimension and therefore no size and no shape. Because of this, these arrays cannot be used in any procedures that require whole arrays. Examples of such procedures are elemental functions such as cos or the function sum. The function SIZE can return results for all but the last dimension, as its size is not known.

In Fortran 77, it was common to pass arrays as assumed-size arrays, but to ensure that they did not pass the upper bounds of the object, they generally passed the size explicitly as an extra argument. This concept is heavily used in the libraries BLAS and LAPACK. In the current days, you could consider them as a folkloric feature of the language.

If you want to pass information about the size and the shape of the argument to a procedure, you should make use of an assumed-shape array. The syntax is similar, but the asterisk is not there. Using an assumed-shape array, the shape of the argument is passed on to the procedure.

More information about this topic can be found in: Assumed size arrays: Colon vs. asterisk - DIMENSION(:) arr vs. arr(*)


note: according to your question, you cannot use an assumed-shape array. If this is not possible, then there is only one way out, pass all dimensions or the full size of the array as an argument to the function. This is the only way.

If you find a way to use assumed-shape arrays, you can easily achieve the result you are interested in, in the following way:

function A1norm(X)
   real(kind=real64), dimension(:,:) :: X
   real(kind=real64)                 :: A1norm
   A1norm = maxval(sum(abs(X),dim=1))
end function

The function ABS is an elemental function which will operate on every element of the array X, returning an array with the same rank of X. This result is passed to the function SUM(...,DIM=1) which is asked to return the sum of the first dimension, creating an array of one lower rank than the original X. Finally, the function MAXVAL picks up the maximum of all thos values.

Again, this is not possible with an assumed-size array due to the elemental procedure abs and the procedure sum which needs to know the size of the object.

kvantour
  • 25,269
  • 4
  • 47
  • 72
0

You can use the assumed shape array A(1:, 1:) in your function Alnorm as follows:

      program hw2
      implicit none
      interface
        real*8 function Alnorm(A)
        implicit none
        real*8 A(1:, 1:), cur
        integer i, j, M, N
        end function Alnorm
      end interface
      real*8 Arr(3, 4), ans
      integer i, j
      read*, ((Arr(i,j), j=1,size(Arr,2)), i=1,size(Arr,1))
      ans = Alnorm(Arr)
      write(*, *) ans
      pause
      end program hw2

      real*8 function Alnorm(A)
      implicit none
      real*8 A(1:, 1:), cur
      integer i, j, M, N
      Alnorm = 0.0
      M = size(A, 1)
      N = size(A, 2)
      do i = 1, N
        cur = 0.0
        do j = 1, M
          cur = cur + A(j,i)
        enddo
        if(Alnorm < cur) then
          Alnorm = cur
        endif
      enddo
      end function Alnorm

Please try to use explicit variable declaration by defining implicit none. It helps to avoid confusion especially for larger Fortran projects. The size function works well to get the rank for the matrix A. Don't forget to define the interface block in your program for function Alnorm.

Considering the comments below your question and using constants M and N for the matrix, your program might look like:

      program hw2
      implicit none
      integer, parameter :: M = 3, N = 4
      real(kind=8) :: Arr(M, N), ans, Alnorm
      integer :: i, j 
      read*, ((Arr(i,j), j=1,N), i=1,M)    
      ans = Alnorm(Arr, M, N)
      write(*, *) ans
      pause
      end program hw2

      real(kind=8) function Alnorm(A, M, N)
      implicit none
      integer, intent(in) :: M, N
      real(kind=8), intent(in):: A(M, N)
      real(kind=8) ::cur
      integer :: i, j
      Alnorm = 0.0
      do i = 1, N
        cur = 0.0
        do j = 1, M
          cur = cur + A(j,i)
        enddo
        if(Alnorm < cur) then
          Alnorm = cur
        endif
      enddo
      end function Alnorm

Tested with Intel Visual Fortran Compiler 19.1.0055.16, both programs write back the maximal sum of a column defined in a M x N matrix.

CKE
  • 1,533
  • 19
  • 18
  • 29