Is there a way to have in Fortran a pointer to an array pointing different targets?
The following code shows what I am trying to do, which does not work as I want since the second association overwrites the first
implicit none
integer, parameter :: n = 3
integer, target :: a(n), b(n)
integer, pointer :: c(:) => NULL()
a = 4
b = 5
c(1:n) => a(1:n)
c(n+1:2*n) => b(1:n)
c(1:2*n) = 1
print*, a
print*, b
OUTPUT (ifort)
4 1 1
1 1 1
OUTPUT (gfortran)
4 4 4
1 1 1
And, any idea why ifort and gfortran behave differently in this case?
No, there is no simple way to do this, at least as far as I can see. Maybe if you say why you are trying to do this somebody might come up with a suitable answer, for instance in my mind derived types and/or array constructors might be the way to go but without context it is difficult to say.
As for why you get different answers you accessed an array out of bounds so anything can happen:
ian#ian-pc:~/test/stack$ cat point.f90
Program point
implicit none
integer, parameter :: n = 3
integer, target :: a(n), b(n)
integer, pointer :: c(:) => NULL()
a = 4
b = 5
c(1:n) => a(1:n)
c(n+1:2*n) => b(1:n)
c(1:2*n) = 1
print*, a
print*, b
End Program point
ian#ian-pc:~/test/stack$ nagfor -C=all -C=undefined point.f90
NAG Fortran Compiler Release 5.3.1(907)
[NAG Fortran Compiler normal termination]
ian#ian-pc:~/test/stack$ ./a.out
Runtime Error: point.f90, line 14: Subscript 1 of C (value 1) is out of range (4:6)
Program terminated by fatal error
Aborted (core dumped)
Think carefully what the lines
c(1:n) => a(1:n)
c(n+1:2*n) => b(1:n)
are doing. The first line says forget about whatever c was before, now c( 1:n ) is an alias for a( 1:n ). Note the allowed indices for c run from 1 to n. Similarly the second line throws away the reference to a and says c( n+1:2*n) is an alias for b( 1:n ). Note now the indices of C run from n+1:2*n, while for b they run from 1:n, but this is fine as both have n elements and that is all that matters. However the next line says
c(1:2*n) = 1
which can not be correct as you have just said the lowest allowed index for C is n+1, and as n=3 1 is not a valid index. Thus you are out of bounds and so anything can happen.
I strongly suggest when developing you use the debugging options on the compiler - in my experience it can save you hours by avoiding this kind of thing!
Related
I am trying to find the smallest index containing the value i in a sorted array. If this i value is not present I want -1 to be returned. I am using a binary search recursive subroutine. The problem is that I can't really stop this recursion and I get lot of answers(one right and the rest wrong). And sometimes I get an error called "segmentation fault: 11" and I don't really get any results.
I've tried to delete this call random_number since I already have a sorted array in my main program, but it did not work.
program main
implicit none
integer, allocatable :: A(:)
real :: MAX_VALUE
integer :: i,j,n,s, low, high
real :: x
N= 10 !size of table
MAX_VALUE = 10
allocate(A(n))
s = 5 ! searched value
low = 1 ! lower limit
high = n ! highest limit
!generate random table of numbers (from 0 to 1000)
call Random_Seed
do i=1, N
call Random_Number(x) !returns random x >= 0 and <1
A(i)= anint(MAX_VALUE*x)
end do
call bubble(n,a)
print *,' '
write(*,10) (a(i),i=1,N)
10 format(10i6)
call bsearch(A,n,s,low,high)
deallocate(A)
end program main
The sort subroutine:
subroutine sort(p,q)
implicit none
integer(kind=4), intent(inout) :: p, q
integer(kind=4) :: temp
if (p>q) then
temp = p
p = q
q = temp
end if
return
end subroutine sort
The bubble subroutine:
subroutine bubble(n,arr)
implicit none
integer(kind=4), intent(inout) :: n
integer(kind=4), intent(inout) :: arr(n)
integer(kind=4) :: sorted(n)
integer :: i,j
do i=1, n
do j=n, i+1, -1
call sort(arr(j-1), arr(j))
end do
end do
return
end subroutine bubble
recursive subroutine bsearch(b,n,i,low,high)
implicit none
integer(kind=4) :: b(n)
integer(kind=4) :: low, high
integer(kind=4) :: i,j,x,idx,n
real(kind=4) :: r
idx = -1
call random_Number(r)
x = low + anint((high - low)*r)
if (b(x).lt.i) then
low = x + 1
call bsearch(b,n,i,low,high)
else if (b(x).gt.i) then
high = x - 1
call bsearch(b,n,i,low,high)
else
do j = low, high
if (b(j).eq.i) then
idx = j
exit
end if
end do
end if
! Stop if high = low
if (low.eq.high) then
return
end if
print*, i, 'found at index ', idx
return
end subroutine bsearch
The goal is to get the same results as my linear search. But I'am getting either of these answers.
Sorted table:
1 1 2 4 5 5 6 7 8 10
5 found at index 5
5 found at index -1
5 found at index -1
or if the value is not found
2 2 3 4 4 6 6 7 8 8
Segmentation fault: 11
There are a two issues causing your recursive search routine bsearch to either stop with unwanted output, or result in a segmentation fault. Simply following the execution logic of your program at the hand of the examples you provided, elucidate the matter:
1) value present and found, unwanted output
First, consider the first example where array b contains the value i=5 you are searching for (value and index pointed out with || in the first two lines of the code block below). Using the notation Rn to indicate the the n'th level of recursion, L and H for the lower- and upper bounds and x for the current index estimate, a given run of your code could look something like this:
b(x): 1 1 2 4 |5| 5 6 7 8 10
x: 1 2 3 4 |5| 6 7 8 9 10
R0: L x H
R1: Lx H
R2: L x H
5 found at index 5
5 found at index -1
5 found at index -1
In R0 and R1, the tests b(x).lt.i and b(x).gt.i in bsearch work as intended to reduce the search interval. In R2 the do-loop in the else branch is executed, idx is assigned the correct value and this is printed - as intended. However, a return statement is now encountered which will return control to the calling program unit - in this case that is first R1(!) where execution will resume after the if-else if-else block, thus printing a message to screen with the initial value of idx=-1. The same happens upon returning from R0 to the main program. This explains the (unwanted) output you see.
2) value not present, segmentation fault
Secondly, consider the example resulting in a segmentation fault. Using the same notation as before, a possible run could look like this:
b(x): 2 2 3 4 4 6 6 7 8 8
x: 1 2 3 4 5 6 7 8 9 10
R0: L x H
R1: L x H
R2: L x H
R3: LxH
R4: H xL
.
.
.
Segmentation fault: 11
In R0 to R2 the search interval is again reduced as intended. However, in R3 the logic fails. Since the search value i is not present in array b, one of the .lt. or .gt. tests will always evaluate to .true., meaning that the test for low .eq. high to terminate a search is never reached. From this point onwards, the logic is no longer valid (e.g. high can be smaller than low) and the code will continue deepening the level of recursion until the call stack gets too big and a segmentation fault occurs.
These explained the main logical flaws in the code. A possible inefficiency is the use of a do-loop to find the lowest index containing a searched for value. Consider a case where the value you are looking for is e.g. i=8, and that it appears in the last position in your array, as below. Assume further that by chance, the first guess for its position is x = high. This implies that your code will immediately branch to the do-loop, where in effect a linear search is done of very nearly the entire array, to find the final result idx=9. Although correct, the intended binary search rather becomes a linear search, which could result in reduced performance.
b(x): 2 2 3 4 4 6 6 7 |8| 8
x: 1 2 3 4 5 6 7 8 |9| 10
R0: L xH
8 found at index 9
Fixing the problems
At the very least, you should move the low .eq. high test to the start of the bsearch routine, so that recursion stops before invalid bounds can be defined (you then need an additional test to see if the search value was found or not). Also, notify about a successful search right after it occurs, i.e. after the equality test in your do-loop, or the additional test just mentioned. This still does not address the inefficiency of a possible linear search.
All taken into account, you are probably better off reading up on algorithms for finding a "leftmost" index (e.g. on Wikipedia or look at a tried and tested implementation - both examples here use iteration instead of recursion, perhaps another improvement, but the same principles apply) and adapt that to Fortran, which could look something like this (only showing new code, ...refer to existing code in your examples):
module mod_search
implicit none
contains
! Function that uses recursive binary search to look for `key` in an
! ordered `array`. Returns the array index of the leftmost occurrence
! of `key` if present in `array`, and -1 otherwise
function search_ordered (array, key) result (idx)
integer, intent(in) :: array(:)
integer, intent(in) :: key
integer :: idx
! find left most array index that could possibly hold `key`
idx = binary_search_left(1, size(array))
! if `key` is not found, return -1
if (array(idx) /= key) then
idx = -1
end if
contains
! function for recursive reduction of search interval
recursive function binary_search_left(low, high) result(idx)
integer, intent(in) :: low, high
integer :: idx
real :: r
if (high <= low ) then
! found lowest possible index where target could be
idx = low
else
! new guess
call random_number(r)
idx = low + floor((high - low)*r)
! alternative: idx = low + (high - low) / 2
if (array(idx) < key) then
! continue looking to the right of current guess
idx = binary_search_left(idx + 1, high)
else
! continue looking to the left of current guess (inclusive)
idx = binary_search_left(low, idx)
end if
end if
end function binary_search_left
end function search_ordered
! Move your routines into a module
subroutine sort(p,q)
...
end subroutine sort
subroutine bubble(n,arr)
...
end subroutine bubble
end module mod_search
! your main program
program main
use mod_search, only : search_ordered, sort, bubble ! <---- use routines from module like so
implicit none
...
! Replace your call to bsearch() with the following:
! call bsearch(A,n,s,low,high)
i = search_ordered(A, s)
if (i /= -1) then
print *, s, 'found at index ', i
else
print *, s, 'not found!'
end if
...
end program main
Finally, depending on your actual use case, you could also just consider using the Fortran intrinsic procedure minloc saving you the trouble of implementing all this functionality yourself. In this case, it can be done by making the following modification in your main program:
! i = search_ordered(a, s) ! <---- comment out this line
j = minloc(abs(a-s), dim=1) ! <---- replace with these two
i = merge(j, -1, a(j) == s)
where j returned from minloc will be the lowest index in the array a where s may be found, and merge is used to return j when a(j) == s and -1 otherwise.
I have a few parameter arrays with different names in a module:
real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...
In a routine in this module
subroutine sub(n,...
...
end
I want to use para1 when n=1, para2 when n=2, etc. There are some solutions to that, one is to make an array paras=[para1,para2...] and index properly which works fine. But I want to try using a pointer
real*8, pointer :: ptr(:)
and assign it to different parameter arrays depending on n, but the problem is that "PARAMETER attribute conflicts with TARGET attribute at (1)". If I remove the parameter attribute, the routine is less safe and the SAVE attribute is assumed.
Am I missing something or why can we not combine parameter and target? And is there a good way around it for this purpose?
The parameter and target attributes indeed conflict. An object with the target attribute must be a variable (Fortran 2018 8.5.17, C861); a named constant (object with the parameter attribute) is not a variable (F2018, 8.5.13, C850).
To use target arrays you must, then, use variables. It is tricky to have a variable which is "safe" from having its value modified by a programming mistake or such. There are several considerations which prohibit a variable from appearing in a variable definition context. If you can arrange such a state, then the compiler may have a chance of detecting your mistake. Can that happen easily?
Outside a pure procedure and an intent(in) dummy argument, the most tempting prohibition is with a protected module variable:
module pars
real, save, target, protected :: para1(74) = [...]
real, save, target, protected :: para2(1) = [6]
end module
subroutine sub (...)
use pars
real, pointer :: p
p => para1
end subroutine sub
Being protected, the values are safe from modification outside the module pars? Alas, even if this were true it isn't helpful: being protected, we can't even point a pointer to module variables.
In summary, your compiler isn't going to find it easy to detect a programming mistake which modifies the variable target array, so if you want to use an array as a target, you'll have to be careful.
Following the suggestion by #ja72 in the comment, this is an attempt to use a single 2D array for the parameters. This works nicely with gfortran-8.2 (on MacOS10.11).
program main
implicit none
integer i
integer, parameter :: para1(*) = [1, 2, 3, 4, 5]
integer, parameter :: para2(*) = [6, 7]
integer, parameter :: N1 = size(para1), N2 = size(para2), N = max(N1, N2)
integer, parameter :: params(N, 2) = &
reshape( [ para1, (0, i = 1, N - N1), &
para2, (0, i = 1, N - N2) ], [N, 2] )
print *, "para1 = ", params( :, 1 )
print *, "para2 = ", params( :, 2 )
print *, "Input i"
read *, i
print *, params( :, i )
end
$ gfortran-8 test.f90 && ./a.out
para1 = 1 2 3 4 5
para2 = 6 7 0 0 0
Input i
1
1 2 3 4 5
However, because the code becomes a bit complicated (because of reshape) and may not work with old compilers, things may be more straightforward to just use non-parameter arrays...
Im working through a Go Ebook.
Here we are creating an array of pointers as so:
sampleArray := [5]*int{0: new(int), 1: new(int)}
As you can see index 0 and index 1 of sampleArray contain initialized integers whereas the remaining indexes contain uninitialized integers.
Then they do the following operation:
*sampleArray[0] = 10
*sampleArray[1] = 20
With that, the values of sampleArray should be:
[0] => address (integer pointer) -> 10
[1] => address (integer pointer) -> 20
[2] => nil (integer pointer)
[3] => nil (integer pointer)
[4] => nil (integer pointer)
My question is, why do we do this:
*sampleArray[0] = 10
*sampleArray[1] = 20
And not this:
sampleArray[0] = 10
sampleArray[1] = 20
To me it looks like we are assigning a value to a pointer which points to another pointer. Shouln't we be assigning the value to the actual memory reference?
Why not then?
&sampleArray[0] = 10
&sampleArray[1] = 20
Im extremely new to pointers so please any thourough assistance would be helpful
This is actually a good question.
The dereferencing operator * has a lower precedence than array access (which in C is equivalent to pointer deref). So *a[x] in Go means "dereference a[x]" and not "dereference a and take element x".
Hope this clarifies things.
I want have a proc which does something if its' argument is a Tcl 8.5 and above dictionary or not.
I could not find anything straightforward from Tcl dict command.
The code which I could get working is:
proc dict? {dicty} {
expr { [catch { dict info $dicty } ] ? 0 : 1 }
}
Is there anything w/o using catch, something built in?Thanks.
You can test if a value is a dictionary by seeing if it is a list and if it has an even number of elements; all even length lists may be used as dictionaries (though many are naturally not canonical dictionaries because of things like duplicate keys).
proc is-dict {value} {
return [expr {[string is list $value] && ([llength $value]&1) == 0}]
}
You can peek at the actual type in Tcl 8.6 with tcl::unsupported::representation but that's not advised because things like literals are converted to dictionaries on the fly. The following is legal, shows what you can do, and shows the limitations (
% set value {b c d e}
b c d e
% tcl::unsupported::representation $value
value is a pure string with a refcount of 4, object pointer at 0x1010072e0, string representation "b c d e"
% dict size $value
2
% tcl::unsupported::representation $value
value is a dict with a refcount of 4, object pointer at 0x1010072e0, internal representation 0x10180fd10:0x0, string representation "b c d e"
% dict set value f g;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x10101eb10:0x0, no string representation
% string length $value
11
% tcl::unsupported::representation $value
value is a string with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x100901890:0x0, string representation "b c d e f g"
% dict size $value;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x1008c7510:0x0, string representation "b c d e f g"
As you can see, types are a bit slippery in Tcl (by design) so you're strongly advised to not rely on them at all.
Your approach is flawed because Tcl has dynamic type system where the actual type of a value is able to morph dynamically and depends on the commands applied to it—observe:
$ tclsh
% info pa
8.5.11
% dict info {a b}
1 entries in table, 4 buckets
number of buckets with 0 entries: 3
number of buckets with 1 entries: 1
number of buckets with 2 entries: 0
number of buckets with 3 entries: 0
number of buckets with 4 entries: 0
number of buckets with 5 entries: 0
number of buckets with 6 entries: 0
number of buckets with 7 entries: 0
number of buckets with 8 entries: 0
number of buckets with 9 entries: 0
number of buckets with 10 or more entries: 0
average search distance for entry: 1.0
% llength {a b}
2
% string len {a b}
3
%
As you can see, the same value {a b} is a dictionary, a list and a string: in each case, the value acquires its "real" type in the very moment a Tcl command expecting a value of certain type converts the "default" type of the value, which is string, to the one the command operates on.
You should understand by now that trying to make a call dict? {a b} has little sence as the value {a b} is a perfect dict as well as a perfect list as well as a perfect string, and it could be, say, a perfect tuple if there are custom commands in the current interpreter working on tuples (lists of fixed length).
Hence the real approach you should take is to just blindly use dict command on those values passed to your commands you expect to contain dictionaries. If a user will manage to pass to your command something which is not interpretable as a dictionary, the dict command will fail, and that's a good thing to do as such an error is not really recoverable (it's a programming error).
Any attempt to count on a value's specific type is going again the grain of the very idea of the Tcl's implicit/dynamic typing. It's even true for the Tcl C API.
If you really meant to ask how to be sure the current Tcl version supports dict command, and not about the type of a particular value, test the Tcl's version somewhere at startup and save this as a flag, like this:
set hasDicts [expr {[package vcompare [info tclversion] 8.5] >= 0}]
But note that your code relying on the hasDicts value is now in some gray zone because if the user is not supplying you values you process with the dict command then what command you use to process them?
Please also note that the dict command can be added to a Tcl 8.4 interpreter in the form of the loadable module (see this).
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.