For Programmers: Free Programming Magazines  


Home > Archive > Fortran > February 2005 > rank mismatch









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author rank mismatch
Bart Vandewoestyne

2005-02-17, 4:05 pm

Suppose the following program:


program test_array_arguments

implicit none

integer :: x(2,3)

x(:,1) = (/ 1, 1 /)
x(:,2) = (/ 2, 2 /)
x(:,3) = (/ 3, 3 /)

! This works
print *, f(x)

! If i only have one single point, it fails...
!print *, f(x(:,1))

contains

function f(x) result (y)

integer :: x(:,:)
integer :: y(size(x,2))

y = sum(x, dim=1)

end function f

end program test_array_arguments


The x represent s-dimensional points. The rows of x represent the
dimensions, the colums of x represent the number of points. So in this
case I have three two-dimensional points.

Now I want to write a f(x) that can evaluate the function f in these
points. To simplify things, just take the function values to be the sum
of all coordinates as in this example.

All works well when the number of columns of x (the number of
2-dimensional points) is bigger than 1, but when I only have one
two-dimensional point, and try to evaluate in that point, i get this
error at compile time:

Error: Rank mismatch for assumed-shape array in parameter 'x' at (1)

I understand that the rank of x(:,1) is not two but 1, but i don't know
how to overcome this problem.

I'm afraid I will have to write two versions of f(x)... one for the rank
2 case and one for the rank 1 case... is this correct? Or is there
another way, which avoids the need of making two versions for each of my
functions.

Thanks,
Bart

--
"Share what you know. Learn what you don't."
Michael Metcalf

2005-02-17, 4:05 pm


"Bart Vandewoestyne" <MyFirstName.MyLastName@telenet.be> wrote in message
news:1108650686.909430@seven.kulnet.kuleuven.ac.be...
> I'm afraid I will have to write two versions of f(x)... one for the rank
> 2 case and one for the rank 1 case... is this correct? Or is there
> another way, which avoids the need of making two versions for each of my
> functions.
>


You can write two versions yet reference them via a generic name ("Fortran
90/95 Explained", Section 5.18).

Regards,

Mike Metcalf

module sums
interface f
module procedure f, f_1
end interface

contains

function f_1(x) result (y)

integer :: x(:)
integer :: y

y = sum(x)

end function f_1

function f(x) result (y)

integer :: x(:,:)
integer :: y(size(x,2))

y = sum(x, dim=1)

end function f

end module sums

program test_array_arguments
use sums
implicit none

integer :: x(2,3)

x(:,1) = (/ 1, 1 /)
x(:,2) = (/ 2, 2 /)
x(:,3) = (/ 3, 3 /)

print *, f(x)
print *, f(x(:,1))

end program test_array_arguments


Rich Townsend

2005-02-17, 4:05 pm

Bart Vandewoestyne wrote:

<snip>

I have posted a solution to this problem in the other thread you started
("elemental functions").

cheers,

Rich
Erik Edelmann

2005-02-17, 4:05 pm

On 2005-02-17, Bart Vandewoestyne <MyFirstName.MyLastName@telenet.be> wrote:
> Suppose the following program:
>
>
> program test_array_arguments
>
> implicit none
>
> integer :: x(2,3)
>
> x(:,1) = (/ 1, 1 /)
> x(:,2) = (/ 2, 2 /)
> x(:,3) = (/ 3, 3 /)
>
> ! This works
> print *, f(x)
>
> ! If i only have one single point, it fails...
> !print *, f(x(:,1))
>
> contains
>
> function f(x) result (y)
>
> integer :: x(:,:)
> integer :: y(size(x,2))
>
> y = sum(x, dim=1)
>
> end function f
>
> end program test_array_arguments


<...>

> I understand that the rank of x(:,1) is not two but 1, but i don't know
> how to overcome this problem.
>
> I'm afraid I will have to write two versions of f(x)... one for the rank
> 2 case and one for the rank 1 case... is this correct? Or is there
> another way, which avoids the need of making two versions for each of my
> functions.


You could replace x(:,1) by x(:,1:1), which is a rank 2 array (with only
one column, but it is still rank 2). Another possibility is to use reshape,
e.g.

integer :: x(2)

<...>

print *, f(reshape(x, (/2,1/)))

If this is better than writting a separate function to handle rank 1
arguments is a matter of taste I guess. If I needed to call f with rank 1
arguments very often I would probably prefer to write a separate function.


Erik
Pierre Asselin

2005-02-17, 4:05 pm

Bart Vandewoestyne <MyFirstName.MyLastName@telenet.be> wrote:

> integer :: x(2,3)
> [ ... ]
> ! This works
> print *, f(x)
> [ ... ]
> ! If i only have one single point, it fails...
> !print *, f(x(:,1))


Did you try this?
print *, f(x(: , 1:1))


--
pa at panix dot com
Bart Vandewoestyne

2005-02-17, 4:05 pm

In article <cv2ate$lfl$02$1@news.t-online.com>, Michael Metcalf wrote:
>
> You can write two versions yet reference them via a generic name ("Fortran
> 90/95 Explained", Section 5.18).


OK, thanks... I am getting closer... but now I have another problem... I
have:

interface f_c0
module procedure f_c0_rank2, f_c0_rank1
end interface f_c0

which defines 2 versions for my function, one for rank 2 arrays and one
for rank 1 arrays (single points).

I try to use f_c0 as an argument to another function, namely:

nb_errors = nb_errors + assert_dp( f_c0(x(:,1), params), 0.9417645335842487_dp, tol)

But when I try to compile, i get:

"Generic name F_C0 used as an actual argument"


So I can't use the generic name f_c0 as an actual argument?

Regards,
Bart

--
"Share what you know. Learn what you don't."
Rich Townsend

2005-02-17, 4:05 pm

Bart Vandewoestyne wrote:
> In article <cv2ate$lfl$02$1@news.t-online.com>, Michael Metcalf wrote:
>
>
>
> OK, thanks... I am getting closer... but now I have another problem... I
> have:
>
> interface f_c0
> module procedure f_c0_rank2, f_c0_rank1
> end interface f_c0
>
> which defines 2 versions for my function, one for rank 2 arrays and one
> for rank 1 arrays (single points).
>
> I try to use f_c0 as an argument to another function, namely:
>
> nb_errors = nb_errors + assert_dp( f_c0(x(:,1), params), 0.9417645335842487_dp, tol)
>
> But when I try to compile, i get:
>
> "Generic name F_C0 used as an actual argument"
>
>
> So I can't use the generic name f_c0 as an actual argument?


No, when you use a procedure as an argument, it must be a specific name
rather than a generic name. This is to prevent the rules for procedure
disambiguation (so-called type-kind-rank matching) from becoming even
more complicated than they already are.

cheers,

Rich
Michael Metcalf

2005-02-17, 4:05 pm


"Bart Vandewoestyne" <MyFirstName.MyLastName@telenet.be> wrote in message
news:1108656507.127889@seven.kulnet.kuleuven.ac.be...
> In article <cv2ate$lfl$02$1@news.t-online.com>, Michael Metcalf wrote:
>
>
> So I can't use the generic name f_c0 as an actual argument?
>


Correct. If you really do have only these two ranks, and you want to use the
function as an actual argument, it might be better to use the neat x(:, 1:1)
form already suggested.

Regards,

Mike


Rich Townsend

2005-02-17, 4:05 pm

Michael Metcalf wrote:
> "Bart Vandewoestyne" <MyFirstName.MyLastName@telenet.be> wrote in message
> news:1108656507.127889@seven.kulnet.kuleuven.ac.be...
>
>
>
> Correct. If you really do have only these two ranks, and you want to use the
> function as an actual argument, it might be better to use the neat x(:, 1:1)
> form already suggested.
>


Or, if at all possible, upgrade to an F95 compiler; I believe you can
use an ELEMENTAL procedure as an actual argument.

cheers,

Rich
Ken Fairfield

2005-02-17, 4:05 pm

Bart Vandewoestyne wrote:
> In article <cv2ate$lfl$02$1@news.t-online.com>, Michael Metcalf wrote:
>
>
>
> OK, thanks... I am getting closer... but now I have another problem... I
> have:
>
> interface f_c0
> module procedure f_c0_rank2, f_c0_rank1
> end interface f_c0
>
> which defines 2 versions for my function, one for rank 2 arrays and one
> for rank 1 arrays (single points).
>
> I try to use f_c0 as an argument to another function, namely:
>
> nb_errors = nb_errors + assert_dp( f_c0(x(:,1), params), 0.9417645335842487_dp, tol)
>
> But when I try to compile, i get:
>
> "Generic name F_C0 used as an actual argument"
>
>
> So I can't use the generic name f_c0 as an actual argument?


Others have clarified that you can't pass a generic name as
an actual argument. Fine. But as written, that's not what's
going on here, at least to my eyes. Is there a typo in your
example?

It sure looks to me like you're passing the _result_ of a
generic function as an actual, "f_c0(x(:,1), params)", and I
don't see any problem with that. It would be different if the
call looked like,

nb_errors = nb_errors + assert_dp( f_c0, x(:,1), params, ...

where the function name "f_c0" was the argument.

Experts???

-Ken
--
I don't speak for Intel, Intel doesn't speak for me...

Ken Fairfield
D1C Automation VMS System Support
who: kenneth dot h dot fairfield
where: intel dot com

Richard E Maine

2005-02-17, 4:05 pm

In article <cv2khi$ckb$1@news01.intel.com>,
Ken Fairfield <my.full.name@intel.com> wrote:

> Bart Vandewoestyne wrote:
[color=darkred]
>
> Others have clarified that you can't pass a generic name as
> an actual argument. Fine. But as written, that's not what's
> going on here, at least to my eyes. Is there a typo in your
> example?
>
> It sure looks to me like you're passing the _result_ of a
> generic function as an actual, "f_c0(x(:,1), params)", and I
> don't see any problem with that.


Good point. Really good point. I had quickly skimmed over this thread
because it looked like others had already given perfectly good answers.
But I'm going to agree with you on this, Ken. It has at least somewhat
the smell of a compiler bug. I wouldn't quite commit to that without a
complete compilable sample to make sure that I hadn't missed important
context, but at least the general smell is in the air.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2005-02-17, 4:05 pm

"Rich Townsend" <rhdt@barVOIDtol.udel.edu> wrote in message
news:cv2h5c$5f8$1@scrotar.nss.udel.edu...

> Or, if at all possible, upgrade to an F95 compiler; I believe you can
> use an ELEMENTAL procedure as an actual argument.


Nope. There is a constraint in f95 prohibiting passing a non-
intrinsic elemental procedure as an actual argument. Last I saw
it was still there in f03.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Bart Vandewoestyne

2005-02-17, 8:58 pm

In article <cv2khi$ckb$1@news01.intel.com>, Ken Fairfield wrote:
>


I should clarify the situation... i made a mistake in my copy-paste
actions...

> Others have clarified that you can't pass a generic name as
> an actual argument. Fine.


OK. If I'm correct, this is due to the following line in my code:

call sim_mc(transpose(x), f_c0, params, f_c0_exact(s, params), &
res, abs_err, rel_err)

Here I pass the *function*, not the result. From what I've learned from
your answers, this is not possible with the generic function name f_c0.

> But as written, that's not what's
> going on here, at least to my eyes. Is there a typo in your
> example?


Yes there was. I misinterpreted my compiler error messages and looked
in the wrong file. The file where the *result* of f_c0 is passed
compiles fine.

> It sure looks to me like you're passing the _result_ of a
> generic function as an actual, "f_c0(x(:,1), params)", and I
> don't see any problem with that. It would be different if the
> call looked like,
>
> nb_errors = nb_errors + assert_dp( f_c0, x(:,1), params, ...
>
> where the function name "f_c0" was the argument.


This is indeed the kind of call where my compiler is complaining.

Sorry for the confusion I have brought in this thread via a bad
copy-paste ;-)

I think my best option is *not* to create two versions (one for rank 1
and one for rank 2 arrays) of my f_c0, but to simply pass x(:,1:1) as an
argument if i want to evaluate in one single point.

Thanks for all your suggestions, this newsgroup is great to learn
Fortran programming!

Regards,
Bart

--
"Share what you know. Learn what you don't."
Bart Vandewoestyne

2005-02-17, 8:58 pm

In article <45OdnXiAP-3PeonfRVn-iA@comcast.com>, James Van Buskirk wrote:
>
>
> Nope. There is a constraint in f95 prohibiting passing a non-
> intrinsic elemental procedure as an actual argument. Last I saw
> it was still there in f03.


For the record: I am using an the NagWare f95 compiler, and sometimes
also g95.

But looking what is written here, it seems i shouldn't even try to find a
solution with ELEMENTAL...

I guess my best choice is just to stick with the x(:,1:1) if i want to
evaluate my function in a single point.

Regards,
Bart

--
"Share what you know. Learn what you don't."
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com