Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29361 Discussions

Determining the length of an input matrix

WSinc
New Contributor I
1,113 Views

Rather than specifically stating the length of an input matrix, how would one

aumtomatically determine that from the calling sequence. I tried using Ubound, but the

compiler doesn't like that, it say it is not determinable. And LEN is supposed to be

for character strings.

Here is a simple example;

--------------------------------------------------------------------------------------------------------

integer*1 a(200)

integer*2 asum, sum

asum=sum(a(3:24))

integer*2 function  sum(a)

integer*4 na(1)

na=UBOUND(a) ! apparently not the right one

sum=0

do ia=1,na(1)

sum=sum+a(ia)

enddo

end

--------------------------------------------------------------------

I realize the FORTRAN already has a sum function, this is just an example.

In the above case, its supposed to give a value of 22 for length, since 22 elements are

being passed. I looked at the FORTRAN HELP, but could not find the proper function, if one exists

for getting the length of the passed array.

This would of course get more complicated for 2 or 3 dimensional arrays, since the length would be passed to an array

rather than a scalar.

0 Kudos
10 Replies
Steven_L_Intel1
Employee
1,113 Views

Hmm - thought I had replied to this.

Your sample source is somewhat confusing - you never declare the argument a in sum and na comes from - where?

There are generally two ways to get the bounds of a dummy argument. The modern way is to declare the argument as an assumed-shape array, with dimension (:). This requires that an explicit interface be visible to the caller, so the subroutine either has to be in a module or in a CONTAINS section. The older way is to pass the bound as a separate argument and use that in the declaration. For example:

subroutine sub(a,n)
integer n
real a(n)

With either of these you can use UBOUND (and LBOUND), and SIZE. SIZE gives you the number of elements, UBOUND gives the upper bound (which might not be the number of elements if the lower bound is not 1. Note that UBOUND by default returns an array of bounds, if you want a specific one add the DIM= argument.

Perhaps you should pick up one of any number of books teaching "modern Fortran". 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,113 Views

[fortran]

integer*2 function  sum(a)
  implicit none
  integer, intent(in) :: a(:) ! assumed shape
  integer :: ia, sum
  sum=0

  do ia=lbound(a, DIM=1),ubound(a, DIM=1)
    sum=sum+a(ia)
  enddo
end
[/fortran]

Then place that into a CONTAINS section of a module that you USE in your program.
Alternatively, you can place an interface to the function, into a module, or into the variable declaration of a procedure.

[fortran]
interface
  integer*2 function  sum(a)
    implicit none
    integer, intent(in) :: a(:) ! assumed shape
  end function sum
end interface
[/fortran]

Jim Dempsey

0 Kudos
WSinc
New Contributor I
1,113 Views

I will try the SIZE function. I have two books about Fortran, but they are not very helpful re this question.

0 Kudos
WSinc
New Contributor I
1,113 Views

Maybe I got the wrong books? But it would be nice if they gave more examples.

The FORTRAN help on-line is pretty sparse as well.

0 Kudos
John_Campbell
New Contributor II
1,113 Views

Jim,

I can not get lbound and ubound values to be transferred in an interface. See the following example:

[fortran]

    integer*4 aa(1000), n
        interface
       integer*2 function  bb (a)
         integer, intent(in) :: a(:) ! assumed shape
       end function bb
    end interface

    n =  bb (aa)        ; write (*,*) 'bb(aa)       =',n
    n =  bb (aa(5:33))  ; write (*,*) 'bb(aa(5:33)) =',n

    end

    integer*2 function  bb (a)
      integer, intent(in) :: a(:) ! assumed shape
      write (*,*) 'lbound', lbound (a, DIM=1)
      write (*,*) 'ubound', ubound (a, DIM=1)
      write (*,*) 'size  ', size (a)
      bb = size (a) * kind (a)
     end[/fortran]

John

 

 

0 Kudos
Steven_L_Intel1
Employee
1,113 Views

Our documentation is meant as a reference, not a tutorial. That said, the description of UBOUND, at least, is far from sparse and includes examples.

0 Kudos
Steven_L_Intel1
Employee
1,113 Views

John, are you expecting that you'll see bounds of 5:33 when you pass aa(5:33)? That's not how the language works. The bounds in the caller are not used - the lower bound starts at 1 unless declared otherwise and the upper bound is the extent.

0 Kudos
John_Campbell
New Contributor II
1,113 Views

Steve,

Your response implies I am expecting too much of the language.
I understand that this is how the language presently works, but would it have been unreasonable to expect it to provide the bounds via an INTERFACE, rather than just the SIZE ?
The purpose of the INTERFACE was to improve on the F77 explicit bounds definition and provide the dimension information of an array. It has clearly stoped short on providing the bounds definition. In the past I wanted to find out this information for an array section and was disappointed with the result.

John

0 Kudos
IanH
Honored Contributor III
1,113 Views

Consider the general case - what if your procedure bb was called with the expression `aa(11:20) + aa(25:34)` as an argument.  What would the bounds inside the procedure be then? 

You could probably come up with some guidelines as to how it could work in some alternative Fortran universe, but I think they would end up being rather complicated, and in places counter-intuitive.

0 Kudos
Steven_L_Intel1
Employee
1,113 Views

Ian has it exactly right - not to mention something like aa(11:20:3). The standard chose a definition that works for all possible manner of arguments. It makes it easier to write a procedure that takes array arguments as you always know what the lower bound is. If you have a situation where you need to preserve the bounds exactly, pass a pointer to a pointer.

0 Kudos
Reply