Skip to content

Commit 223cba3

Browse files
authored
Merge pull request #1 from PierUgit/rcp2
Update cmplx-real-pointers.txt
2 parents 483ee87 + 812cc69 commit 223cba3

File tree

1 file changed

+54
-24
lines changed

1 file changed

+54
-24
lines changed

proposals/cmplx-real-pointers.txt

+54-24
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,44 @@ at some point:
3535
! ...
3636
allocate( r1(n), r2(n), r3(n) )
3737
! ... some computations on r1(:) and r2(:) as reals
38-
call rfft(r1)
39-
call rfft(r2)
40-
call fftconvol(r1,r2,r3,n/2) ! called without any interface
38+
call rfft(r1) ; call rfft(r2)
39+
call fftconvol(r1,r2,r3,n/2) ! called without any interface,
40+
! hence type mismatchs
4141
call irfft(r3)
4242
! ... some computations on r3(:) as real
4343
end program
4444

45+
! dangling routine (not contained and not in a module)
4546
subroutine fftconvol(c1,c2,c3,n)
4647
integer, intent(in) :: n
4748
complex, intent(in) :: c1(n), c2(n)
4849
complex, intent(out) :: c3(n)
4950
c3(:) = c1(:) * c2(:)
5051
end subroutine
5152

53+
With modern Fortran another trick has got quite popular, by using the
54+
C interoperability features. Nonetheless the trick is non standard:
55+
56+
program foo
57+
use iso_c_binding
58+
real, allocatable :: r1(:), r2(:), r3(:)
59+
integer, parameter :: n = 100000
60+
complex, pointer :: c1(:), c2(:), c3(:)
61+
! ...
62+
allocate( r1(n), r2(n), r3(n) )
63+
! ... some computations on r1(:) and r2(:) as reals
64+
call rfft(r1) ; call rfft(r2)
65+
! non-standard trick
66+
call c_f_pointer( c_loc(r1), c1, [n/2] )
67+
call c_f_pointer( c_loc(r2), c2, [n/2] )
68+
call c_f_pointer( c_loc(r3), c3, [n/2] )
69+
70+
c3(:) = c1(:) * c2(:)
71+
72+
call irfft(r3)
73+
! ... some computations on r3(:) as real
74+
end program
75+
5276

5377
3. Proposed solution
5478

@@ -63,11 +87,8 @@ vice-versa. The above code would become:
6387
! ...
6488
allocate( r1(n), r2(n), r3(n) )
6589
! ... some computations on r1(:) and r2(:) as reals
66-
call rfft(r1)
67-
call rfft(r2)
68-
c1 => r1
69-
c2 => r2
70-
c3 => r3
90+
call rfft(r1) ; call rfft(r2)
91+
c1 => r1 ; c2 => r2 ; c3 => r3
7192
c3(:) = c1(:) * c2(:)
7293
call irfft(r3)
7394
! ... some computations on r3(:) as real
@@ -80,26 +101,26 @@ used, with additional rules and restrictions:
80101

81102
`c => r`
82103

83-
- `r` is a *contiguous* real array, which has either the target or the
84-
pointer attribute
85-
- `c` is a complex array pointer of the same kind as `r`, and of the same
86-
rank by default (but pointer rank remapping can be used)
87-
- `c` can also be a complex scalar pointer, in the case where r is a
104+
- `r` shall be a *contiguous* real array, which has either the target
105+
or the pointer attribute
106+
- `c` shall be a complex array pointer of the same kind as `r`, and of
107+
the same rank by default (but pointer rank remapping can be used)
108+
- `c` could also be a complex scalar pointer, in the case r is a
88109
rank-1 array of size 2
89110
- the size of the first dimension of `r` shall be even
90-
- `c%re` refers to the same storage as `r(1::2)` (rank-1), or
111+
- `c%re` shall refer to the same storage as `r(1::2)` (rank-1), or
91112
`r(1::2,:)` (rank-2), etc...
92-
- `c%im` refers to the same storage as `r(2::2)` (rank-1), or
113+
- `c%im` shall refer to the same storage as `r(2::2)` (rank-1), or
93114
`r(2::2,:)` (rank-2), etc...
94115

95116
`r => c`
96117

97118
- the exact opposite
98-
- `c` is a *contiguous* complex array or a complex scalar, which has
99-
either the target or the pointer attribute
100-
- `r` is a real array pointer of the same kind as `c`, and of the same
101-
rank by default (but pointer rank remapping can be used)
102-
- if `c` is a scalar, then `r` is a rank-1 pointer of size 2
119+
- `c` shall be a *contiguous* complex array or a complex scalar, which
120+
has either the target or the pointer attribute
121+
- `r` shall be a real array pointer of the same kind as `c`, and of the
122+
same rank by default (but pointer rank remapping can be used)
123+
- if `c` is a scalar, then `r` shall be a rank-1 pointer of size 2
103124
- same other rules as above
104125

105126
3.2 Alternative syntaxes
@@ -126,9 +147,16 @@ r => real :: c
126147
```
127148

128149
Something generic (that is, not `complex_pointer()` or `real_pointer()`)
129-
may be desirable in case other inter-type pointer association would be
150+
may be desirable in case other inter-type pointer associations would be
130151
allowed in future versions of the standard.
131152

153+
3.3 Prototyping, etc...
154+
155+
I think that this proposal doesn't need to have a preliminary prototype
156+
implementation, as it essentially consists in standardizing an already
157+
existing and common practice. A prototype implementation would do
158+
nothing else than mimicing the `c_f_pointer()` trick.
159+
132160

133161
4. Issues / Objections / Limitations
134162

@@ -158,16 +186,18 @@ In this case, `c%re` would refer to the same storage as `r(1:n/2)`.
158186

159187
Allowing a real actual argument to be associated to a complex dummy
160188
argument -and vice-versa- has also been considered, but it would raise
161-
backward compatibility issues. So this part has been dropped.
189+
backward compatibility issues. So this part has been dropped from the
190+
proposal.
162191

163192
4.3. Alignment
164193

165194
Considering for instance a default real type stored on 4 bytes, the
166195
default complex type is stored on 8 bytes. Compilers may prefer/want to
167-
align complex arrays on 16 bytes boundaries, which cannot be guaranteed
196+
align the complex arrays on 8 bytes boundaries, which cannot be guaranteed
168197
if a complex pointer is associated to an arbitrary real array
169198
(e.g. `c => r(2:)`). If this is a problem, the pointer association may be
170-
allowed only in the other way (real pointer associated to a complex array).
199+
allowed only the other way (real pointer associated to a complex array),
200+
where alignement should not be a problem.
171201

172202

173203
5. References

0 commit comments

Comments
 (0)