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

📄 kdtree2.f90

📁 kd tree java implementation 2
💻 F90
📖 第 1 页 / 共 4 页
字号:
                      return                   endif                endif             end do                          !             ! if we are still here then we need to search mroe.             !             call search(nfarther)          endif       endif    end if  end subroutine search  real(kdkind) function dis2_from_bnd(x,amin,amax) result (res)    real(kdkind), intent(in) :: x, amin,amax    if (x > amax) then       res = (x-amax)**2;       return    else       if (x < amin) then          res = (amin-x)**2;          return       else          res = 0.0          return       endif    endif    return  end function dis2_from_bnd  logical function box_in_search_range(node, sr) result(res)    !    ! Return the distance from 'qv' to the CLOSEST corner of node's    ! bounding box    ! for all coordinates outside the box.   Coordinates inside the box    ! contribute nothing to the distance.    !    type (tree_node), pointer :: node    type (tree_search_record), pointer :: sr    integer :: dimen, i    real(kdkind)    :: dis, ballsize    real(kdkind)    :: l, u    dimen = sr%dimen    ballsize = sr%ballsize    dis = 0.0    res = .true.    do i=1,dimen       l = node%box(i)%lower       u = node%box(i)%upper       dis = dis + (dis2_from_bnd(sr%qv(i),l,u))       if (dis > ballsize) then          res = .false.          return       endif    end do    res = .true.    return  end function box_in_search_range  subroutine process_terminal_node(node)    !    ! Look for actual near neighbors in 'node', and update    ! the search results on the sr data structure.    !    type (tree_node), pointer          :: node    !    real(kdkind), pointer          :: qv(:)    integer, pointer       :: ind(:)    real(kdkind), pointer          :: data(:,:)    !    integer                :: dimen, i, indexofi, k, centeridx, correltime    real(kdkind)                   :: ballsize, sd, newpri    logical                :: rearrange    type(pq), pointer      :: pqp     !    ! copy values from sr to local variables    !    !    ! Notice, making local pointers with an EXPLICIT lower bound    ! seems to generate faster code.    ! why?  I don't know.    qv => sr%qv(1:)     pqp => sr%pq    dimen = sr%dimen    ballsize = sr%ballsize     rearrange = sr%rearrange    ind => sr%ind(1:)    data => sr%Data(1:,1:)         centeridx = sr%centeridx    correltime = sr%correltime    !    doing_correl = (centeridx >= 0)  ! Do we have a decorrelation window?     !    include_point = .true.    ! by default include all points    ! search through terminal bucket.    mainloop: do i = node%l, node%u       if (rearrange) then          sd = 0.0          do k = 1,dimen             sd = sd + (data(k,i) - qv(k))**2             if (sd>ballsize) cycle mainloop          end do          indexofi = ind(i)  ! only read it if we have not broken out       else          indexofi = ind(i)          sd = 0.0          do k = 1,dimen             sd = sd + (data(k,indexofi) - qv(k))**2             if (sd>ballsize) cycle mainloop          end do       endif       if (centeridx > 0) then ! doing correlation interval?          if (abs(indexofi-centeridx) < correltime) cycle mainloop       endif       !        ! two choices for any point.  The list so far is either undersized,       ! or it is not.       !       ! If it is undersized, then add the point and its distance       ! unconditionally.  If the point added fills up the working       ! list then set the sr%ballsize, maximum distance bound (largest distance on       ! list) to be that distance, instead of the initialized +infinity.        !       ! If the running list is full size, then compute the       ! distance but break out immediately if it is larger       ! than sr%ballsize, "best squared distance" (of the largest element),       ! as it cannot be a good neighbor.        !       ! Once computed, compare to best_square distance.       ! if it is smaller, then delete the previous largest       ! element and add the new one.        if (sr%nfound .lt. sr%nn) then          !          ! add this point unconditionally to fill list.          !          sr%nfound = sr%nfound +1           newpri = pq_insert(pqp,sd,indexofi)          if (sr%nfound .eq. sr%nn) ballsize = newpri          ! we have just filled the working list.          ! put the best square distance to the maximum value          ! on the list, which is extractable from the PQ.        else          !          ! now, if we get here,          ! we know that the current node has a squared          ! distance smaller than the largest one on the list, and          ! belongs on the list.           ! Hence we replace that with the current one.          !          ballsize = pq_replace_max(pqp,sd,indexofi)       endif    end do mainloop    !    ! Reset sr variables which may have changed during loop    !    sr%ballsize = ballsize   end subroutine process_terminal_node  subroutine process_terminal_node_fixedball(node)    !    ! Look for actual near neighbors in 'node', and update    ! the search results on the sr data structure, i.e.    ! save all within a fixed ball.    !    type (tree_node), pointer          :: node    !    real(kdkind), pointer          :: qv(:)    integer, pointer       :: ind(:)    real(kdkind), pointer          :: data(:,:)    !    integer                :: nfound    integer                :: dimen, i, indexofi, k    integer                :: centeridx, correltime, nn    real(kdkind)                   :: ballsize, sd    logical                :: rearrange    !    ! copy values from sr to local variables    !    qv => sr%qv(1:)    dimen = sr%dimen    ballsize = sr%ballsize     rearrange = sr%rearrange    ind => sr%ind(1:)    data => sr%Data(1:,1:)    centeridx = sr%centeridx    correltime = sr%correltime    nn = sr%nn ! number to search for    nfound = sr%nfound    ! search through terminal bucket.    mainloop: do i = node%l, node%u       !        ! two choices for any point.  The list so far is either undersized,       ! or it is not.       !       ! If it is undersized, then add the point and its distance       ! unconditionally.  If the point added fills up the working       ! list then set the sr%ballsize, maximum distance bound (largest distance on       ! list) to be that distance, instead of the initialized +infinity.        !       ! If the running list is full size, then compute the       ! distance but break out immediately if it is larger       ! than sr%ballsize, "best squared distance" (of the largest element),       ! as it cannot be a good neighbor.        !       ! Once computed, compare to best_square distance.       ! if it is smaller, then delete the previous largest       ! element and add the new one.        ! which index to the point do we use?        if (rearrange) then          sd = 0.0          do k = 1,dimen             sd = sd + (data(k,i) - qv(k))**2             if (sd>ballsize) cycle mainloop          end do          indexofi = ind(i)  ! only read it if we have not broken out       else          indexofi = ind(i)          sd = 0.0          do k = 1,dimen             sd = sd + (data(k,indexofi) - qv(k))**2             if (sd>ballsize) cycle mainloop          end do       endif       if (centeridx > 0) then ! doing correlation interval?          if (abs(indexofi-centeridx)<correltime) cycle mainloop       endif       nfound = nfound+1       if (nfound .gt. sr%nalloc) then          ! oh nuts, we have to add another one to the tree but          ! there isn't enough room.          sr%overflow = .true.       else          sr%results(nfound)%dis = sd          sr%results(nfound)%idx = indexofi       endif    end do mainloop    !    ! Reset sr variables which may have changed during loop    !    sr%nfound = nfound  end subroutine process_terminal_node_fixedball  subroutine kdtree2_n_nearest_brute_force(tp,qv,nn,results)     ! find the 'n' nearest neighbors to 'qv' by exhaustive search.    ! only use this subroutine for testing, as it is SLOW!  The    ! whole point of a k-d tree is to avoid doing what this subroutine    ! does.    type (kdtree2), pointer :: tp    real(kdkind), intent (In)       :: qv(:)    integer, intent (In)    :: nn    type(kdtree2_result)    :: results(:)     integer :: i, j, k    real(kdkind), allocatable :: all_distances(:)    ! ..    allocate (all_distances(tp%n))    do i = 1, tp%n       all_distances(i) = square_distance(tp%dimen,qv,tp%the_data(:,i))    end do    ! now find 'n' smallest distances    do i = 1, nn       results(i)%dis =  huge(1.0)       results(i)%idx = -1    end do    do i = 1, tp%n       if (all_distances(i)<results(nn)%dis) then          ! insert it somewhere on the list          do j = 1, nn             if (all_distances(i)<results(j)%dis) exit          end do          ! now we know 'j'          do k = nn - 1, j, -1             results(k+1) = results(k)          end do          results(j)%dis = all_distances(i)          results(j)%idx = i       end if    end do    deallocate (all_distances)  end subroutine kdtree2_n_nearest_brute_force    subroutine kdtree2_r_nearest_brute_force(tp,qv,r2,nfound,results)     ! find the nearest neighbors to 'qv' with distance**2 <= r2 by exhaustive search.    ! only use this subroutine for testing, as it is SLOW!  The    ! whole point of a k-d tree is to avoid doing what this subroutine    ! does.    type (kdtree2), pointer :: tp    real(kdkind), intent (In)       :: qv(:)    real(kdkind), intent (In)       :: r2    integer, intent(out)    :: nfound    type(kdtree2_result)    :: results(:)     integer :: i, nalloc    real(kdkind), allocatable :: all_distances(:)    ! ..    allocate (all_distances(tp%n))    do i = 1, tp%n       all_distances(i) = square_distance(tp%dimen,qv,tp%the_data(:,i))    end do        nfound = 0    nalloc = size(results,1)    do i = 1, tp%n       if (all_distances(i)< r2) then          ! insert it somewhere on the list          if (nfound .lt. nalloc) then             nfound = nfound+1             results(nfound)%dis = all_distances(i)             results(nfound)%idx = i          endif       end if    enddo    deallocate (all_distances)    call kdtree2_sort_results(nfound,results)  end subroutine kdtree2_r_nearest_brute_force  subroutine kdtree2_sort_results(nfound,results)    !  Use after search to sort results(1:nfound) in order of increasing     !  distance.    integer, intent(in)          :: nfound    type(kdtree2_result), target :: results(:)     !    !    !THIS IS BUGGY WITH INTEL FORTRAN    !    If (nfound .Gt. 1) Call heapsort(results(1:nfound)%dis,results(1:nfound)%ind,nfound)    !    if (nfound .gt. 1) call heapsort_struct(results,nfound)    return  end subroutine kdtree2_sort_results  subroutine heapsort(a,ind,n)    !    ! Sort a(1:n) in ascending order, permuting ind(1:n) similarly.    !     ! If ind(k) = k upon input, then it will give a sort index upon output.    !    integer,intent(in)          :: n    real(kdkind), intent(inout)         :: a(:)     integer, intent(inout)      :: ind(:)    !    !    real(kdkind)        :: value   ! temporary for a value from a()    integer     :: ivalue  ! temporary for a value from ind()    integer     :: i,j    integer     :: ileft,iright    ileft=n/2+1    iright=n    !    do i=1,n    !       ind(i)=i    ! Generate initial idum array    !    end do    if(n.eq.1) return                      do        if(ileft > 1)then          ileft=ileft-1          value=a(ileft); ivalue=ind(ileft)       else          value=a(iright); ivalue=ind(iright)          a(iright)=a(1); ind(iright)=ind(1)          iright=iright-1          if (iright == 1) then             a(1)=value;ind(1)=ivalue             return          endif       endif       i=ileft       j=2*ileft       do while (j <= iright)           if(j < iright) then             if(a(j) < a(j+1)) j=j+1          endif          if(value < a(j)) then             a(i)=a(j); ind(i)=ind(j)             i=j             j=j+j          else             j=iright+1          endif       end do       a(i)=value; ind(i)=ivalue    end do  end subroutine heapsort  subroutine heapsort_struct(a,n)    !    ! Sort a(1:n) in ascending order    !     !    integer,intent(in)                 :: n    type(kdtree2_result),intent(inout) :: a(:)    !    !    type(kdtree2_result) :: value ! temporary value    integer     :: i,j    integer     :: ileft,iright    ileft=n/2+1    iright=n    !    do i=1,n    !       ind(i)=i    ! Generate initial idum array    !    end do    if(n.eq.1) return                      do        if(ileft > 1)then          ileft=ileft-1          value=a(ileft)       else          value=a(iright)          a(iright)=a(1)          iright=iright-1          if (iright == 1) then             a(1) = value             return          endif       endif       i=ileft       j=2*ileft       do while (j <= iright)           if(j < iright) then             if(a(j)%dis < a(j+1)%dis) j=j+1          endif          if(value%dis < a(j)%dis) then             a(i)=a(j);              i=j             j=j+j          else             j=iright+1          endif       end do       a(i)=value    end do  end subroutine heapsort_structend module kdtree2_module

⌨️ 快捷键说明

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