Degenerate Conic

Algorithms • Modern Fortran Programming • Orbital Mechanics

Jul 08, 2014

Unique

Here is a simple Fortran subroutine to return only the unique values in a vector (inspired by Matlab's unique function). Note, this implementation is for integer arrays, but could easily be modified for any type. This code is not particularly optimized, so there may be a more efficient way to do it. It does demonstrate Fortran array transformational functions such as pack and count. Note that to duplicate the Matlab function, the output array must also be sorted.

subroutine unique(vec,vec_unique)  
! Return only the unique values from vec.

implicit none

integer,dimension(:),intent(in) :: vec  
integer,dimension(:),allocatable,intent(out) :: vec_unique

integer :: i,num  
logical,dimension(size(vec)) :: mask

mask = .false.

do i=1,size(vec)

    !count the number of occurrences of this element:  
    num = count( vec(i)==vec )

    if (num==1) then  
        !there is only one, flag it:  
        mask(i) = .true.  
    else  
        !flag this value only if it hasn't already been flagged:  
        if (.not. any(vec(i)==vec .and. mask) ) mask(i) = .true.  
    end if

end do

!return only flagged elements:  
allocate( vec_unique(count(mask)) )  
vec_unique = pack( vec, mask )

!if you also need it sorted, then do so.  
! For example, with slatec routine:  
!call ISORT (vec_unique, [0], size(vec_unique), 1)

end subroutine unique