⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdtree2.f90

📁 kd tree java implementation 2
💻 F90
📖 第 1 页 / 共 4 页
字号:
      ! ..      v => tp%the_data(1:,1:)      ind => tp%ind(1:)      smin = v(c,ind(l))      smax = smin      ulocal = u      do i = l + 2, ulocal, 2         lmin = v(c,ind(i-1))         lmax = v(c,ind(i))         if (lmin>lmax) then            t = lmin            lmin = lmax            lmax = t         end if         if (smin>lmin) smin = lmin         if (smax<lmax) smax = lmax      end do      if (i==ulocal+1) then         last = v(c,ind(ulocal))         if (smin>last) smin = last         if (smax<last) smax = last      end if      interv%lower = smin      interv%upper = smax    end subroutine spread_in_coordinate  subroutine kdtree2_destroy(tp)    ! Deallocates all memory for the tree, except input data matrix    ! .. Structure Arguments ..    type (kdtree2), pointer :: tp    ! ..    call destroy_node(tp%root)    deallocate (tp%ind)    nullify (tp%ind)    if (tp%rearrange) then       deallocate(tp%rearranged_data)       nullify(tp%rearranged_data)    endif    deallocate(tp)    return  contains    recursive subroutine destroy_node(np)      ! .. Structure Arguments ..      type (tree_node), pointer :: np      ! ..      ! .. Intrinsic Functions ..      intrinsic ASSOCIATED      ! ..      if (associated(np%left)) then         call destroy_node(np%left)         nullify (np%left)      end if      if (associated(np%right)) then         call destroy_node(np%right)         nullify (np%right)      end if      if (associated(np%box)) deallocate(np%box)      deallocate(np)      return          end subroutine destroy_node  end subroutine kdtree2_destroy  subroutine kdtree2_n_nearest(tp,qv,nn,results)    ! Find the 'nn' vectors in the tree nearest to 'qv' in euclidean norm    ! returning their indexes and distances in 'indexes' and 'distances'    ! arrays already allocated passed to this subroutine.    type (kdtree2), pointer      :: tp    real(kdkind), target, intent (In)    :: qv(:)    integer, intent (In)         :: nn    type(kdtree2_result), target :: results(:)    sr%ballsize = huge(1.0)    sr%qv => qv    sr%nn = nn    sr%nfound = 0    sr%centeridx = -1    sr%correltime = 0    sr%overflow = .false.     sr%results => results    sr%nalloc = nn   ! will be checked    sr%ind => tp%ind    sr%rearrange = tp%rearrange    if (tp%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    sr%dimen = tp%dimen    call validate_query_storage(nn)     sr%pq = pq_create(results)    call search(tp%root)    if (tp%sort) then       call kdtree2_sort_results(nn, results)    endif!    deallocate(sr%pqp)    return  end subroutine kdtree2_n_nearest  subroutine kdtree2_n_nearest_around_point(tp,idxin,correltime,nn,results)    ! Find the 'nn' vectors in the tree nearest to point 'idxin',    ! with correlation window 'correltime', returing results in    ! results(:), which must be pre-allocated upon entry.    type (kdtree2), pointer        :: tp    integer, intent (In)           :: idxin, correltime, nn    type(kdtree2_result), target   :: results(:)    allocate (sr%qv(tp%dimen))    sr%qv = tp%the_data(:,idxin) ! copy the vector    sr%ballsize = huge(1.0)       ! the largest real(kdkind) number    sr%centeridx = idxin    sr%correltime = correltime    sr%nn = nn    sr%nfound = 0    sr%dimen = tp%dimen    sr%nalloc = nn    sr%results => results    sr%ind => tp%ind    sr%rearrange = tp%rearrange    if (sr%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    call validate_query_storage(nn)    sr%pq = pq_create(results)    call search(tp%root)    if (tp%sort) then       call kdtree2_sort_results(nn, results)    endif    deallocate (sr%qv)    return  end subroutine kdtree2_n_nearest_around_point  subroutine kdtree2_r_nearest(tp,qv,r2,nfound,nalloc,results)     ! find the nearest neighbors to point 'idxin', within SQUARED    ! Euclidean distance 'r2'.   Upon ENTRY, nalloc must be the    ! size of memory allocated for results(1:nalloc).  Upon    ! EXIT, nfound is the number actually found within the ball.     !    !  Note that if nfound .gt. nalloc then more neighbors were found    !  than there were storage to store.  The resulting list is NOT    !  the smallest ball inside norm r^2     !    ! Results are NOT sorted unless tree was created with sort option.    type (kdtree2), pointer      :: tp    real(kdkind), target, intent (In)    :: qv(:)    real(kdkind), intent(in)             :: r2    integer, intent(out)         :: nfound    integer, intent (In)         :: nalloc    type(kdtree2_result), target :: results(:)    !    sr%qv => qv    sr%ballsize = r2    sr%nn = 0      ! flag for fixed ball search    sr%nfound = 0    sr%centeridx = -1    sr%correltime = 0    sr%results => results    call validate_query_storage(nalloc)    sr%nalloc = nalloc    sr%overflow = .false.     sr%ind => tp%ind    sr%rearrange= tp%rearrange    if (tp%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    sr%dimen = tp%dimen    !    !sr%dsl = Huge(sr%dsl)    ! set to huge positive values    !sr%il = -1               ! set to invalid indexes    !    call search(tp%root)    nfound = sr%nfound    if (tp%sort) then       call kdtree2_sort_results(nfound, results)    endif    if (sr%overflow) then       write (*,*) 'KD_TREE_TRANS: warning! return from kdtree2_r_nearest found more neighbors'       write (*,*) 'KD_TREE_TRANS: than storage was provided for.  Answer is NOT smallest ball'       write (*,*) 'KD_TREE_TRANS: with that number of neighbors!  I.e. it is wrong.'    endif    return  end subroutine kdtree2_r_nearest  subroutine kdtree2_r_nearest_around_point(tp,idxin,correltime,r2,&   nfound,nalloc,results)    !    ! Like kdtree2_r_nearest, but around a point 'idxin' already existing    ! in the data set.     !     ! Results are NOT sorted unless tree was created with sort option.    !    type (kdtree2), pointer      :: tp    integer, intent (In)         :: idxin, correltime, nalloc    real(kdkind), intent(in)             :: r2    integer, intent(out)         :: nfound    type(kdtree2_result), target :: results(:)    ! ..    ! .. Intrinsic Functions ..    intrinsic HUGE    ! ..    allocate (sr%qv(tp%dimen))    sr%qv = tp%the_data(:,idxin) ! copy the vector    sr%ballsize = r2    sr%nn = 0    ! flag for fixed r search    sr%nfound = 0    sr%centeridx = idxin    sr%correltime = correltime    sr%results => results    sr%nalloc = nalloc    sr%overflow = .false.    call validate_query_storage(nalloc)    !    sr%dsl = HUGE(sr%dsl)    ! set to huge positive values    !    sr%il = -1               ! set to invalid indexes    sr%ind => tp%ind    sr%rearrange = tp%rearrange    if (tp%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    sr%rearrange = tp%rearrange    sr%dimen = tp%dimen    !    !sr%dsl = Huge(sr%dsl)    ! set to huge positive values    !sr%il = -1               ! set to invalid indexes    !    call search(tp%root)    nfound = sr%nfound    if (tp%sort) then       call kdtree2_sort_results(nfound,results)    endif    if (sr%overflow) then       write (*,*) 'KD_TREE_TRANS: warning! return from kdtree2_r_nearest found more neighbors'       write (*,*) 'KD_TREE_TRANS: than storage was provided for.  Answer is NOT smallest ball'       write (*,*) 'KD_TREE_TRANS: with that number of neighbors!  I.e. it is wrong.'    endif    deallocate (sr%qv)    return  end subroutine kdtree2_r_nearest_around_point  function kdtree2_r_count(tp,qv,r2) result(nfound)    ! Count the number of neighbors within square distance 'r2'.     type (kdtree2), pointer   :: tp    real(kdkind), target, intent (In) :: qv(:)    real(kdkind), intent(in)          :: r2    integer                   :: nfound    ! ..    ! .. Intrinsic Functions ..    intrinsic HUGE    ! ..    sr%qv => qv    sr%ballsize = r2    sr%nn = 0       ! flag for fixed r search    sr%nfound = 0    sr%centeridx = -1    sr%correltime = 0        nullify(sr%results) ! for some reason, FTN 95 chokes on '=> null()'    sr%nalloc = 0            ! we do not allocate any storage but that's OK                             ! for counting.    sr%ind => tp%ind    sr%rearrange = tp%rearrange    if (tp%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    sr%dimen = tp%dimen    !    !sr%dsl = Huge(sr%dsl)    ! set to huge positive values    !sr%il = -1               ! set to invalid indexes    !    sr%overflow = .false.    call search(tp%root)    nfound = sr%nfound    return  end function kdtree2_r_count  function kdtree2_r_count_around_point(tp,idxin,correltime,r2) &   result(nfound)    ! Count the number of neighbors within square distance 'r2' around    ! point 'idxin' with decorrelation time 'correltime'.    !    type (kdtree2), pointer :: tp    integer, intent (In)    :: correltime, idxin    real(kdkind), intent(in)        :: r2    integer                 :: nfound    ! ..    ! ..    ! .. Intrinsic Functions ..    intrinsic HUGE    ! ..    allocate (sr%qv(tp%dimen))    sr%qv = tp%the_data(:,idxin)    sr%ballsize = r2    sr%nn = 0       ! flag for fixed r search    sr%nfound = 0    sr%centeridx = idxin    sr%correltime = correltime    nullify(sr%results)    sr%nalloc = 0            ! we do not allocate any storage but that's OK                             ! for counting.    sr%ind => tp%ind    sr%rearrange = tp%rearrange    if (sr%rearrange) then       sr%Data => tp%rearranged_data    else       sr%Data => tp%the_data    endif    sr%dimen = tp%dimen    !    !sr%dsl = Huge(sr%dsl)    ! set to huge positive values    !sr%il = -1               ! set to invalid indexes    !    sr%overflow = .false.    call search(tp%root)    nfound = sr%nfound    return  end function kdtree2_r_count_around_point  subroutine validate_query_storage(n)    !    ! make sure we have enough storage for n    !    integer, intent(in) :: n    if (size(sr%results,1) .lt. n) then       write (*,*) 'KD_TREE_TRANS:  you did not provide enough storage for results(1:n)'       stop       return    endif    return  end subroutine validate_query_storage  function square_distance(d, iv,qv) result (res)    ! distance between iv[1:n] and qv[1:n]     ! .. Function Return Value ..    ! re-implemented to improve vectorization.    real(kdkind) :: res    ! ..    ! ..    ! .. Scalar Arguments ..    integer :: d    ! ..    ! .. Array Arguments ..    real(kdkind) :: iv(:),qv(:)    ! ..    ! ..    res = sum( (iv(1:d)-qv(1:d))**2 )  end function square_distance    recursive subroutine search(node)    !    ! This is the innermost core routine of the kd-tree search.  Along    ! with "process_terminal_node", it is the performance bottleneck.     !    ! This version uses a logically complete secondary search of    ! "box in bounds", whether the sear    !    type (Tree_node), pointer          :: node    ! ..    type(tree_node),pointer            :: ncloser, nfarther    !    integer                            :: cut_dim, i    ! ..    real(kdkind)                               :: qval, dis    real(kdkind)                               :: ballsize    real(kdkind), pointer           :: qv(:)    type(interval), pointer :: box(:)     if ((associated(node%left) .and. associated(node%right)) .eqv. .false.) then       ! we are on a terminal node       if (sr%nn .eq. 0) then          call process_terminal_node_fixedball(node)       else          call process_terminal_node(node)       endif    else       ! we are not on a terminal node       qv => sr%qv(1:)       cut_dim = node%cut_dim       qval = qv(cut_dim)       if (qval < node%cut_val) then          ncloser => node%left          nfarther => node%right          dis = (node%cut_val_right - qval)**2!          extra = node%cut_val - qval       else          ncloser => node%right          nfarther => node%left          dis = (node%cut_val_left - qval)**2!          extra = qval- node%cut_val_left       endif       if (associated(ncloser)) call search(ncloser)       ! we may need to search the second node.        if (associated(nfarther)) then          ballsize = sr%ballsize!          dis=extra**2          if (dis <= ballsize) then             !             ! we do this separately as going on the first cut dimen is often             ! a good idea.             ! note that if extra**2 < sr%ballsize, then the next             ! check will also be false.              !             box => node%box(1:)             do i=1,sr%dimen                if (i .ne. cut_dim) then                   dis = dis + dis2_from_bnd(qv(i),box(i)%lower,box(i)%upper)                   if (dis > ballsize) then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -