I have a type that stores an array:
type data
type(someType) pointer :: someTypePtr(:)
end type
I assign something to someTypePtr with
type(data), intent(inout) :: this
integer, intent(in) :: lb, ub
type(someType), target, intent(in) :: sometype(lb:ub)
this%someTypePtr => sometype
Later on I create a c_ptr pointing to the instance I just reffered to as this. When I cast this pointer back to a fortran type afterwards, the lower bound starts with 0:
type(c_ptr) :: ptr
type(someType) :: data
call c_f_pointer(ptr, data)
write(*,*) lbound(data%someTypePtr) !will give 0
Is there something similar to reshape to change the someTypePtr back to it's original lbound:ubound?
It is strange, it should be 1, not 0. Anyway, you can remap the pointer afterwards:
use iso_c_binding
real(c_float), pointer :: ptr(:)
type(c_ptr) :: ptr_c
allocate(ptr(5:6))
ptr_c = c_loc(ptr(lbound(ptr)))
call c_f_pointer(ptr_c, ptr, [2])
print *, lbound(ptr)
ptr(5:6) => ptr
print *, lbound(ptr)
end
run:
> ./a.out
1
5
Related
I have the following Fortran program. But I don't understand why the output is 4 instead of 1. I am using GNU 6.4 Fortran compiler:
program aa
implicit none
real, pointer, dimension(:,:) :: t => null()
integer :: i,j
allocate(t(0:100,20))
do i = 0, 100
do j = 1, 20
t(i,j) = i*j
end do
end do
call te(t(1:,:))
stop
contains
subroutine te(a)
implicit none
real,dimension(:,:),pointer,intent(in) :: a
print *, a(1,1)
end subroutine te
end program aa
The Intel compiler 18.0.2 returns the error message
/pt.f90(17): error #7121: A ptr dummy may only be argument associated with a ptr, and this array element or section does not inherit the POINTER attr from its parent array. [T]
call te(t(1:,:))
Change the line in your subroutine to
real,dimension(:,:),intent(in) :: a
and all is good.
I wrote a recursive program on Fortran to calculate the combinations of npoints of ndim dimensions as follows. I first wrote this program on MATLAB and it was perfectly running. But in Fortran, my problem is that after the first iteration it is assigning absurd values for the list of points, with no explanation. Could somebody give me a hand?
PROGRAM MAIN
IMPLICIT NONE
INTEGER :: ndim, k, npontos, contador,i,iterate, TEST
integer, dimension(:), allocatable :: pontos
print*, ' '
print*, 'npoints?'
read *, npontos
print*, 'ndim?'
read *, ndim
k=1
contador = 1
open(450,file= 'combination.out',form='formatted',status='unknown')
write(450,100) 'Comb ','stat ',(' pt ',i,' ',i=1,ndim)
write(450,120) ('XXXXXXXXXX ',i=1,ndim+1)
allocate(pontos(ndim))
do i=1,4
pontos(i)=i
end do
TEST = iterate(pontos, ndim, npontos,k,contador)
end program MAIN
recursive integer function iterate(pontos, ndim, npontos, k,contador)
implicit NONE
integer, intent(in) :: ndim, k, npontos
integer,dimension(:) :: pontos
integer contador,inic,i,j,m
if (k.eq.ndim) then
inic=pontos(ndim)
do i = pontos(ndim),npontos
pontos(k)= i
write(*,*) pontos(:)
contador=contador+1
end do
pontos(ndim)= inic + 1
else
inic = pontos (k)
do j = pontos(k),(npontos-ndim+k)
pontos(k)=j
pontos= iterate(pontos, ndim, npontos, k+1,contador)
end do
end if
pontos(k)=inic+1;
if (pontos(k).gt.(npontos-ndim+k+1)) then
do m =k+1,ndim
pontos(m)=pontos(m-1)+1
end do
end if
end function iterate
There are too many issues in that code... I stopped debugging it. This is what I got so far, it's too much for a comment.
This doesn't make sense:
pontos= iterate(pontos, ndim, npontos, k+1,contador)
You are changing pontos inside iterate, and never set a return value within the function.
You need to a) provide a result statement for recursive functions (and actually set it) or b) convert it to a subroutine. Since you are modifying at least one dummy argument, you should go with b).
Since you are using assumed-shape dummy arguments, you need to specify an interface to the function/subroutine, either explicitly or with a module.
Neither format 100 nor format 120 are specified in your code.
Using the low-level GNU Science Library bindings Bindings.Gsl.RandomNumberGeneration, I'm running into this odd type behavior in GHCi where binding changes return type from a peek into GHC.Prim.Any. I'm trying to understand why since I can't use the c'rng_alloc unless I retain the type of pointer to an rng. For eample:
λ> :t c'gsl_rng_alloc
c'gsl_rng_alloc :: Ptr C'gsl_rng_type -> IO (Ptr C'gsl_rng)
λ> :t p'gsl_rng_mt19937
p'gsl_rng_mt19937 :: Ptr (Ptr gsl_rng_type)
λ> :t peek p'gsl_rng_mt19937
peek p'gsl_rng_mt19937 :: IO (Ptr gsl_rng_type)
λ> x <- peek p'gsl_rng_mt19937
λ> :t x
x :: Ptr GHC.Prim.Any
λ> c'gsl_rng_alloc x
<interactive>:421:17:
Couldn't match type ‘GHC.Prim.Any’ with ‘C'gsl_rng_type’
Expected type: Ptr C'gsl_rng_type
Actual type: Ptr GHC.Prim.Any
In the first argument of ‘c'gsl_rng_alloc’, namely ‘x’
In the expression: c'gsl_rng_alloc x
λ>
Trying to explicitly specify the type of the peek return that doesn't help either:
λ> x <- (peek p'gsl_rng_mt19937) :: IO (Ptr gsl_rng_type)
λ> :t x
x :: Ptr GHC.Prim.Any
To expand somewhat on #user2407038's comment:
When you do x <- peek (ptr :: Ptr (Ptr a)) in the GHCi prompt, the type variable a must be instantiated to some concrete type. This is because the do notation x <- peek p means peek p >>= \x -> ..., where ... is what you type into GHCi afterwards. Since GHCi can't know the future, it has to "cheat" during typechecking.
Recall that in peek p >>= \x -> ..., the right-hand argument to >>=, namely the lambda abstraction \x -> ..., is monomorphic in its argument. This is why GHCi has to assign a monomorphic type to x.
GHC.Prim.Any is the placeholder type that GHC uses in situations like this where a concrete, monomorphic type needs to be assigned to something that has no other constraints.
I am new to Fortran. I am writing a program in Fortran 90 to get non-zero elements of an array and put them into a new array using pointer function as following:
program prog
implicit none
integer, target :: a(5)
integer :: i
integer, pointer :: nz(:)
a(1) = 1
a(2) = 0
a(3) = 0
a(4) = 2
a(5) = 3
nz => non_zeros(a)
do i=1, size(nz)
write(*,*) nz(i)
end do
contains
function non_zeros(a)
integer, target :: a(:)
integer, pointer:: non_zeros(:)
integer :: n, i, j
n = count(a .ne. 0)
allocate(non_zeros(n))
j = 0
do i=1, m
if (a(i) .ne. 0) then
j = j + 1
non_zeros(j) => a(i)
end if
end do
end function non_zeros
end program prog
during compiling I got the error:
non_zeros(j) => a(i)
1
Error: Expected bounds specification for 'non_zeros' at (1)
Can you please tell me what did I do wrong? Thank you in advance!
Update of my question: According to the explanation of High Performance Mark, I defined a derived type:
program prog
implicit none
integer, target :: a(5)
type dt
integer, pointer :: x
end type
type(dt), allocatable :: nz(:)
a(1) = 1
a(2) = 0
a(3) = 0
a(4) = 2
a(5) = 3
nz = non_zeros(a)
contains
function non_zeros(a)
integer, target :: a(:)
type(dt), allocatable :: non_zeros(:)
integer :: n, i, j
n = count(a .ne. 0)
allocate(non_zeros(n))
j = 0
do i=1, m
if (a(i) .ne. 0) then
j = j + 1
non_zeros(j)%x => a(i)
end if
end do
end function non_zeros
end program prog
Now program works and gives the desired results. However, I did not use pointer function in this case, since my function returns an allocatable array of pointers, not pointer to an array. Is there any way to use pointer function here? Thank you
To get the non-zero elements of a into a new array you could simply declare
integer, dimension(:), allocatable :: non_zeros
and then populate that with the statement
non_zeros = pack(a,a/=0)
and avoid fiddling around with pointers entirely. This relies on a feature introduced in the 2003 standard, but it is implemented by all (I think) the current crop of Fortran compilers on the market.
The code that you have written looks to me as if you want nz to be an array of pointers, with each element in nz pointing to a non-zero element of a. If I'm right, you've misunderstood what a statement such as
integer, pointer :: nz(:)
declares. It does not declare an array of pointers to integers, it declares a pointer to an array of integers. When you write
non_zeros(j) => a(i)
you're making the mistake of trying to set an element of non_zeros to point to an element of a.
The error message is misleading here because the compiler interprets non_zeros(j) as a syntactically-incorrect bounds-spec or bounds-remapping, but the error is semantic, the compiler doesn't understand your misunderstanding of Fortran.
I am starting this thread because I want to learn how to successfully use the same pointer to serve as the aliases of different array-valued functions, say, f1 and f2, sequentially.
Here is an unsuccessful code to illustrate what I want. Thanks. Lee
PROGRAM main
...
REAL(WP), POINTER, DIMENSION(:) :: p
p=>f1
print*,p(1.0_wp) ! the outcome should be 3
p=>f2
print*,p(2.0_wp) ! the outcome should be 3 1
CONTAINS
FUNCTION f1(x)
IMPLICIT NONE
REAL(WP), TARGET :: f1
REAL(WP), INTENT(IN) :: x
f1=x+2
END FUNCTION f1
FUNCTION f2(x)
IMPLICIT NONE
REAL(WP), TARGET :: f2(2)
REAL(WP), INTENT(IN) :: x
f2(1) = x+1
f2(2) = x-1
END FUNCTION f2
END PROGRAM main
For a pointer to a function that returns an array, you want to have an interface to describe a pointer to a function that returns an array.
Here is an example of how to setup function pointers that might set you in the right direction:
How to alias a function name in Fortran
Edit: OK, here is some example source code:
module ExampleFuncs
implicit none
contains
function f1 (x)
real, dimension (:), allocatable :: f1
real, intent (in) :: x
allocate (f1 (1:2))
f1 (1) = 2.0 * x
f1 (2) = -2.0 * x
return
end function f1
function f2 (x)
real, dimension (:), allocatable :: f2
real, intent (in) :: x
allocate (f2 (1:3))
f2 (1) = x
f2 (2) = x**2
f2 (3) = x**3
return
end function f2
end module ExampleFuncs
program test_func_ptrs
use ExampleFuncs
implicit none
abstract interface
function func (z)
real, dimension (:), allocatable :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr
real :: input
do
write (*, '( // "Input test value: ")', advance="no" )
read (*, *) input
if ( input < 0.0 ) then
f_ptr => f1
else
f_ptr => f2
end if
write (*, '( "evaluate function: ", *(ES14.4) )' ) f_ptr (input)
end do
end program test_func_ptrs