Developer
Developer

Reputation: 8400

Fortran: sparse arrays or lists

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

Answers (2)

haraldkl
haraldkl

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

Francois Jacq
Francois Jacq

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

Related Questions