Reputation: 8400
Is there any implementation of sparse arrays or equivalent lists in Fortran.
In the stage of computation of large data set we pass say an array of size of n=10000
to a subroutine to do some stuff on them. For example, finding similar elements in it and listing them for each item sequentially. That is, for item one, to find all similar items through the list (array) and to store the resulting marks. The resulting could be large as the list for each element. Note that regarding the criteria the similarity we use is not symmetric which means we need to iterate the evaluation for all items fully. The resulting therefore could be in different length for each according to criteria being used. Storing all the results therefore requires sparse arrays/list which is available in Python as:
R = an array # an array
L = [] # list initialization
for e in R: # iteration on all elements of R
r = similars(e,R,criteria) # r is array & different in size for each element
L.append(r) # store the ranks in list L
For simplicity now we use usual arrays in Fortran where for n<=1000
it is n*n
. As you see this is a very inefficient idea for larger sizes.
Any solution?
Upvotes: 2
Views: 964
Reputation: 3819
You might be interested in using Judy-Arrays via the ISO-C-Binding. It provides you the functionality of dynamic sparse arrays. Otherwise I'd recommend Francois Jacq solution maybe with the addition of an additional sorted list of entries, to perform binary searches for given values, if you need that. Both approaches work quite fine in my experience.
Upvotes: 0
Reputation: 1274
A solution without linked list.
Here, one assumes that the vectors "r" contain double precision values.
Notice that this solution uses no pointer, just allocatable arrays, which warrants to avoid memory leaks. The number of reallocations is limited (log2(list%n)) but one accepts to allocate list%result with a size larger than really needed (maximum twice).
At last, the vectors "r" are duplicated in the list (this is not the case in the python version).
module extendable_list
implicit none
type result_type
double precision,allocatable :: vector(:)
end type
type list_type
integer :: n
type(result_type),allocatable :: result(:)
end type
contains
subroutine append(list,r)
type(list_type),intent(inout) :: list
double precision,intent(in) :: r(:)
type(result_type),allocatable :: temporary(:)
integer :: i
if(.not.allocated(list%result)) then
allocate(list%result(10))
list%n=0
else if(list%n >= size(list%result)) then
allocate(temporary(2*list%n))
do i=1,list%n
call move_alloc(list%result(i)%vector,temporary(i)%vector)
enddo
call move_alloc(temporary,list%result)
endif
list%n=list%n+1
allocate(list%result(list%n)%vector(size(r)))
list%result(list%n)%vector=r
end subroutine
end module
program main
use extendable_list
implicit none
type(list_type) :: list
integer :: i
do i=1,10
call append(list,(/1.d0,3.d0/))
call append(list,(/7.d0,-9.d0,45.d0/))
enddo
do i=1,list%n
write(*,*) list%result(i)%vector
enddo
end program
Result :
coul@b10p5001:~/test$ ifort t65.f90
coul@b10p5001:~/test$ ./a.out
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
1.00000000000000 3.00000000000000
7.00000000000000 -9.00000000000000 45.0000000000000
Upvotes: 4