9

I have a simple fortran function that computes the Kronecker product:

function kron(A, B)
    implicit none
    real, intent(in) :: A(:, :), B(:, :)
    integer :: i, j, ma, na, mb, nb
    real, dimension(:, :) :: kron

    ma = ubound(A, 1)
    na = ubound(A, 2)
    mb = ubound(b, 1)
    nb = ubound(b, 2)
    forall(i=1:ma, j=1:na)
        kron(mb*(i-1)+1:mb*i, nb*(j-1)+1:nb*j) = A(i,j)*B
    end forall
end function kron

It's inside a module, but when I compile it with gfortran -static -ffree-form -std=f2003 -Wall, I get these errors:

function kron(A, B)
                1
Error: Array 'kron' at (1) cannot have a deferred shape

Is this error occurring because you're supposed to know the size of the array to be returned beforehand?

Michael A
  • 4,391
  • 8
  • 34
  • 61

3 Answers3

6

That is exactly what the error is telling you: kron must have an explicit shape. If you do not want to pass the array sizes beforehand, you'd have to define kron as

real, dimension(lbound(a,dim=1):ubound(a,dim=1),&
                lbound(a,dim=2):ubound(a,dim=2)) :: kron

Using this particular explicit declaration above does compile for me on gfortran 4.6.3.

Kyle Kanos
  • 3,257
  • 2
  • 23
  • 37
  • Thanks. I guess there isn't a way to do this without calling `lbound` twice for each dimension, right? Since I call it again when I assign to `ma` and the other vars. I corrected the typo in my question too, since `A(i*j)*B` should have been `A(i,j)*B`. – Michael A Sep 12 '13 at 17:16
  • @user2766558 Actually, in looking at this again, you should have dimensions of `(a1*b1,a2*b2)` for the array `kron` where `a1=ubound(a,dim=1) - lbound(a,dim=1) + 1` and similarly for the others. – Kyle Kanos Sep 12 '13 at 17:19
  • Weird. Running the code you gave me does work, but maybe just for my simple example. Wouldn't `a1=size(a, 1)`, `a2=size(a, 2)` work as well? The code compiles/runs properly if I make that change. like [this](http://pastebin.com/nbSDPGTa). – Michael A Sep 12 '13 at 17:25
  • Yes, `size` can work. However, note that if you have `a` or `b` have a starting index of less than 1, you are going to have a small problem with defining `kron` – Kyle Kanos Sep 12 '13 at 17:31
  • I didn't even know that was a possibility. I thought all arrays were 1-indexed in Fortran, but I guess it makes sense for compatibility with C right? I'm just using this code for personal use, and I probably won't be redefining the start index. Unless I missed something else I'll accept your answer. – Michael A Sep 12 '13 at 17:46
  • The incoming arrays are assumed shape (as is the function result, sort of [the compiler error message is perhaps misleading] - the conceptual issue is that there is nothing for the result to assume the shape of). The lower bound of an assumed shape array will be one, unless the programmer overrides the default lower bound in the declaration of `A` and `B` inside the function (the lower bound of the actual argument is not relevant). Dummy arguments and function results can be deferred shape (bounds get passed too) - but deferred shape things always have the allocatable or pointer attribute. – IanH Sep 12 '13 at 21:58
1

A deferred-shape array that has the ALLOCATABLE attribute is referred to as an allocatable array. Its bounds and shape are determined when storage is allocated for it by an ALLOCATE statement.

try this

real, intent(in), allocatable, dimension(:, :: A(:, :), B(:, :)

  • 1
    This cannot work as (a.o.) the number of brackets don't match. How is this related to the return variable / name of the function kron? – albert Oct 25 '18 at 17:21
1

You just need to define the allocatable array as allocatable, i.e replace the kron definition with;

real, allocatable, dimension(:,:) :: kron

This also compiles fine in 4.6.3 and is defined at: https://docs.roguewave.com/codedynamics/2017.0/html/index.html#page/TotalViewLH/totalviewlhug-examining-data.09.10.html

Hopefully this should save you some effort, especially considering there is no need to define a lower bound here!