6

I want to assign complex array as variable. My code is like

        complex indx(3,3)
        integer i,j

        do i=1,3
          do j=1,3
            indx(i,j) = (i,j)                
            write(*,*) indx(i,j)
          end do
        end do

and in this case I am getting an error like

 A symbol must be a defined parameter in this context.   [I]
                       indx(i,j) = (i,j)

2 Answers 2

9

You must use function cmplx to build a complex value you want to assign.

    complex indx(3,3)
    integer i,j

    do i=1,3
      do j=1,3
       indx(i,j) = cmplx(i,j)               
       write(*,*) indx(i,j)
      end do
    end do

The syntax you tried is only valid for constant literals.

Sign up to request clarification or add additional context in comments.

Comments

3

The answer by Vladimir F tells the important part: for (i,j) to be a complex literal constant i and j must be constants.1 As stated there, the intrinsic complex function cmplx can be used in more general cases.

For the sake of some variety and providing options, I'll look at other aspects of complex arrays. In the examples which follow I'll ignore the output statement and assume the declarations given.

We have, then, Vladimir F's correction:

do i=1,3
  do j=1,3
    indx(i,j) = CMPLX(i,j)   ! Note that this isn't in array element order
  end do
end do

We could note, though, that cmplx is an elemental function:

do i=1,3
  indx(i,:) = CMPLX(i,[(j,j=1,3)])
end do

On top of that, we can consider

indx = RESHAPE(CMPLX([((i,i=1,3),j=1,3)],[((j,i=1,3),j=1,3)]),[3,3])

where this time the right-hand side is in array element order for indx.

Well, I certainly won't say that this last (or perhaps even the second) is better than the original loop, but it's an option. In some cases it could be more elegant.

But we've yet other options. If one has compiler support for complex part designators we have an alternative for the first form:

do i=1,3
  do j=1,3
    indx(i,j)%re = i
    indx(i,j)%im = j
  end do
end do

This doesn't really give us anything, but note that we can have the complex part of an array:

do i=1,3
  indx(i,:)%re = [(i,j=1,3)]
  indx(i,:)%im = [(j,j=1,3)]
end do

or

do i=1,3
  indx(i,:)%re = i  ! Using scalar to array assignment
  indx(i,:)%im = [(j,j=1,3)]
end do

And we could go all the way to

indx%re = RESHAPE([((i,i=1,3),j=1,3))],[3,3])
indx%im = RESHAPE([((j,i=1,3),j=1,3))],[3,3])

Again, that's all in the name of variety or for other applications. There's even spread to consider in some of these. But don't hate the person reviewing your code.


1 That's constants not constant expresssions.

2 Comments

tiny remark: as this is an in-depth look you could be paying respect to fortran's column-major ordering, e.g. assign indx(:,j) instead of indx(i,:). can never be to sure if compilers will optimize those loops.
The whole answer could do with a bit of tidying, and contiguous access would be worth a mention. I've been meaning to revise this a touch for a while, so let me see what I can do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.