I'm writing a sparse matrix library in Fortran for fun but came into a little snag. I have a subroutine for matrix multiplication with the interface
subroutine matvec(A,x,y)
class(sparse_matrix), intent(in) :: A
real(double_precision), intent(in) :: x(:)
real(double_precision), intent(inout) :: y(:)
{etc.}
This uses a sparse matrix type that I've defined myself, the implementation of which is unimportant. Now, I can make things nicer and have a lot less code if A
contains an object called iterator
:
type :: sparse_matrix
type(matrix_iterator) :: iterator
{etc.}
which stores a few variables that keep track of things during matvec
. But, if I change the state of iterator
and in turn the state of A
during matrix multiplication, the compiler will throw a fit because A
has intent(in) for that subroutine.
Suppose I change things around and instead define
type :: sparse_matrix
type(matrix_iterator), pointer :: iterator
{etc.}
It's no problem if I change the state of iterator during a procedure in which a matrix has intent(in), because the value of the pointer to iterator doesn't change; only the memory stored at that address is affected. This is confirmed by making a reduced test case, which compiles and runs just fine using GCC.
Am I correct in thinking this is an appropriate fix? Or should I change the subroutine so that A has intent(inout)? The fact that it compiled with GCC doesn't necessarily mean it's standard-compliant, nor does it mean it's good programming practice.
To make an analogy with C, suppose I had a function foo(int* const p)
. If I wrote
*p = 42;
this would be ok, as the value of the pointer doesn't change, only the data stored at the address pointed to. On the other hand, I couldn't write
p = &my_var;
because it's a constant pointer.