19 integer(kind=intType) :: idx
62 integer(kind=intType) :: heap_size = 0
95 integer(kind=intType) :: nalloc
97 nalloc =
size(results_in, 1)
98 if (nalloc .lt. 1)
then
99 write (*, *)
'PQ_CREATE: error, input arrays must be allocated.'
101 res%elems => results_in
139 subroutine heapify(a, i_in)
146 type(
pq),
pointer :: a
147 integer(kind=intType),
intent(in) :: i_in
149 integer(kind=intType) :: i, l, r, largest
151 real(kind=
realtype) :: pri_i, pri_l, pri_r, pri_largest
168 if (l .gt. a%heap_size)
then
172 pri_i = a%elems(i)%dis
173 pri_l = a%elems(l)%dis
174 if (pri_l .gt. pri_i)
then
186 if (r .le. a%heap_size)
then
187 pri_r = a%elems(r)%dis
188 if (pri_r .gt. pri_largest)
then
194 if (largest .ne. i)
then
198 a%elems(i) = a%elems(largest)
199 a%elems(largest) = temp
213 end subroutine heapify
222 type(
pq),
pointer :: a
225 if (a%heap_size .gt. 0)
then
228 write (*, *)
'PQ_MAX: ERROR, heap_size < 1'
236 type(
pq),
pointer :: a
238 if (a%heap_size .gt. 0)
then
241 write (*, *)
'PQ_MAX_PRI: ERROR, heapsize < 1'
254 type(
pq),
pointer :: a
257 if (a%heap_size .ge. 1)
then
266 a%elems(1) = a%elems(a%heap_size)
267 a%heap_size = a%heap_size - 1
271 write (*, *)
'PQ_EXTRACT_MAX: error, attempted to pop non-positive PQ'
283 type(
pq),
pointer :: a
284 real(kind=
realtype),
intent(in) :: dis
285 integer(kind=intType),
intent(in) :: idx
288 integer(kind=intType) :: i, isparent
296 a%heap_size = a%heap_size + 1
300 isparent = int(i / 2)
301 parentdis = a%elems(isparent)%dis
302 if (dis .gt. parentdis)
then
304 a%elems(i)%dis = parentdis
305 a%elems(i)%idx = a%elems(isparent)%idx
322 subroutine pq_adjust_heap(a, i)
324 type(
pq),
pointer :: a
325 integer(kind=intType),
intent(in) :: i
333 integer(kind=intType) :: parent, child, n
343 do while (child .le. n)
344 if (child .lt. n)
then
345 if (a%elems(child)%dis .lt. a%elems(child + 1)%dis)
then
349 prichild = a%elems(child)%dis
350 if (e%dis .ge. prichild)
then
354 a%elems(parent) = a%elems(child)
361 end subroutine pq_adjust_heap
371 type(
pq),
pointer :: a
372 real(kind=
realtype),
intent(in) :: dis
373 integer(kind=intType),
intent(in) :: idx
377 integer(kind=intType) :: parent, child, n
378 real(kind=
realtype) :: prichild, prichildp1
388 loop:
do while (child .le. n)
389 prichild = a%elems(child)%dis
396 if (child .lt. n)
then
397 prichildp1 = a%elems(child + 1)%dis
398 if (prichild .lt. prichildp1)
then
400 prichild = prichildp1
404 if (dis .ge. prichild)
then
410 a%elems(parent) = a%elems(child)
415 a%elems(parent)%dis = dis
416 a%elems(parent)%idx = idx
440 type(
pq),
pointer :: a
441 integer(kind=intType) :: i
443 if ((i .lt. 1) .or. (i .gt. a%heap_size))
then
444 write (*, *)
'PQ_DELETE: error, attempt to remove out of bounds element.'
450 a%elems(i) = a%elems(a%heap_size)
451 a%heap_size = a%heap_size - 1
507 integer(kind=intType) :: cut_dim
513 integer(kind=intType) :: l, u
523 integer(kind=intType) :: dimen = 0, n = 0
525 real(kind=
realtype),
pointer :: the_data(:, :) => null()
539 integer(kind=intType),
pointer :: ind(:) => null()
543 logical :: sort = .false.
545 logical :: rearrange = .false.
546 real(kind=
realtype),
pointer :: rearranged_data(:, :) => null()
564 integer(kind=intType) :: dimen
565 integer(kind=intType) :: nn, nfound
567 integer(kind=intType) :: centeridx = 999, correltime = 9999
569 integer(kind=intType) :: nalloc
577 integer(kind=intType),
pointer :: ind(:)
613 integer(kind=intType),
intent(in),
optional :: dim
614 logical,
intent(in),
optional :: sort
615 logical,
intent(in),
optional :: rearrange
618 real(kind=
realtype),
target :: input_data(:, :)
620 integer(kind=intType) :: i
623 mr%the_data => input_data
626 if (
present(dim))
then
629 mr%dimen =
size(input_data, 1)
631 mr%n =
size(input_data, 2)
635 if (
present(sort))
then
641 if (
present(rearrange))
then
642 mr%rearrange = rearrange
644 mr%rearrange = .true.
647 if (mr%rearrange)
then
648 allocate (mr%rearranged_data(mr%dimen, mr%n))
650 mr%rearranged_data(:, i) = mr%the_data(:, &
654 nullify (mr%rearranged_data)
659 subroutine build_tree(tp)
663 integer(kind=intType) :: j
664 type(
tree_node),
pointer :: dummy => null()
666 allocate (tp%ind(tp%n))
670 tp%root => build_tree_for_range(tp, 1, tp%n, dummy)
671 end subroutine build_tree
673 recursive function build_tree_for_range(tp, l, u, parent)
result(res)
684 integer(kind=intType),
intent(In) :: l, u
687 integer(kind=intType) :: i, c, m, dimen, idim
689 real(kind=
realtype) :: average, left, right, coorspread(tp%dimen), tmp
706 allocate (res%box(dimen))
720 call spread_in_coordinate(tp, i, l, u, res%box(i))
741 if (
associated(parent))
then
742 if (i .ne. parent%cut_dim)
then
747 call spread_in_coordinate(tp, i, l, u, res%box(i))
749 res%box(i) = parent%box(i)
757 coorspread = res%box(1:dimen)%upper - res%box(1:dimen)%lower
761 if (coorspread(i) > tmp)
then
770 call select_on_coordinate(tp%the_data, tp%ind, c, m, l, u)
779 average = sum(tp%the_data(c, tp%ind(l:u))) / real(u - l + 1, kind=
realtype)
781 average = (res%box(c)%upper + res%box(c)%lower) / 2.0
784 res%cut_val = average
794 res%left => build_tree_for_range(tp, l, m, res)
795 res%right => build_tree_for_range(tp, m + 1, u, res)
797 if (
associated(res%right) .eqv. .false.)
then
798 res%box = res%left%box
799 res%cut_val_left = res%left%box(c)%upper
800 res%cut_val = res%cut_val_left
801 elseif (
associated(res%left) .eqv. .false.)
then
802 res%box = res%right%box
803 res%cut_val_right = res%right%box(c)%lower
804 res%cut_val = res%cut_val_right
806 res%cut_val_right = res%right%box(c)%lower
807 res%cut_val_left = res%left%box(c)%upper
808 res%cut_val = (res%cut_val_left + res%cut_val_right) / 2
815 left = res%left%box(idim)%upper
816 right = res%right%box(idim)%upper
817 res%box(idim)%upper = max(left, right)
819 left = res%left%box(idim)%lower
820 right = res%right%box(idim)%lower
822 res%box(idim)%lower = min(left, right)
828 end function build_tree_for_range
850 integer(kind=intType),
intent(In) :: c, li, ui
851 real(kind=
realtype),
intent(in) :: alpha
854 integer(kind=intType) :: ind(1:)
855 integer(kind=intType) :: tmp
857 integer(kind=intType) :: lb, rb
873 if (v(c, ind(lb)) <= alpha)
then
878 tmp = ind(lb); ind(lb) = ind(rb); ind(rb) = tmp
884 if (v(c, ind(lb)) <= alpha)
then
892 subroutine select_on_coordinate(v, ind, c, k, li, ui)
898 integer(kind=intType),
intent(In) :: c, k, li, ui
900 integer(kind=intType) :: i, l, m, s, t, u
903 integer(kind=intType) :: ind(:)
911 if (v(c, ind(i)) < v(c, t))
then
921 if (m <= k) l = m + 1
922 if (m >= k) u = m - 1
924 end subroutine select_on_coordinate
926 subroutine spread_in_coordinate(tp, c, l, u, interv)
936 type(
interval),
intent(out) :: interv
939 integer(kind=intType),
intent(In) :: c, l, u
942 real(kind=
realtype) :: last, lmax, lmin, t, smin, smax
943 integer(kind=intType) :: i, ulocal
946 real(kind=
realtype),
pointer :: v(:, :)
947 integer(kind=intType),
pointer :: ind(:)
949 v => tp%the_data(1:, 1:)
956 do i = l + 2, ulocal, 2
957 lmin = v(c, ind(i - 1))
959 if (lmin > lmax)
then
964 if (smin > lmin) smin = lmin
965 if (smax < lmax) smax = lmax
967 if (i == ulocal + 1)
then
968 last = v(c, ind(ulocal))
969 if (smin > last) smin = last
970 if (smax < last) smax = last
976 end subroutine spread_in_coordinate
984 call destroy_node(tp%root)
989 if (tp%rearrange)
then
990 deallocate (tp%rearranged_data)
991 nullify (tp%rearranged_data)
998 recursive subroutine destroy_node(np)
1004 intrinsic ASSOCIATED
1006 if (
associated(np%left))
then
1007 call destroy_node(np%left)
1010 if (
associated(np%right))
then
1011 call destroy_node(np%right)
1014 if (
associated(np%box))
deallocate (np%box)
1018 end subroutine destroy_node
1028 real(kind=
realtype),
target,
intent(In) :: qv(:)
1029 integer(kind=intType),
intent(In) :: nn
1032 sr%ballsize = huge(1.0)
1038 sr%overflow = .false.
1040 sr%results => results
1045 sr%rearrange = tp%rearrange
1046 if (tp%rearrange)
then
1047 sr%Data => tp%rearranged_data
1049 sr%Data => tp%the_data
1053 call validate_query_storage(nn)
1056 call search(tp%root)
1071 integer(kind=intType),
intent(In) :: idxin, correltime, nn
1074 allocate (sr%qv(tp%dimen))
1075 sr%qv = tp%the_data(:, idxin)
1076 sr%ballsize = huge(1.0)
1077 sr%centeridx = idxin
1078 sr%correltime = correltime
1086 sr%results => results
1089 sr%rearrange = tp%rearrange
1091 if (sr%rearrange)
then
1092 sr%Data => tp%rearranged_data
1094 sr%Data => tp%the_data
1097 call validate_query_storage(nn)
1100 call search(tp%root)
1122 real(kind=
realtype),
target,
intent(In) :: qv(:)
1123 real(kind=
realtype),
intent(in) :: r2
1124 integer(kind=intType),
intent(out) :: nfound
1125 integer(kind=intType),
intent(In) :: nalloc
1136 sr%results => results
1138 call validate_query_storage(nalloc)
1140 sr%overflow = .false.
1142 sr%rearrange = tp%rearrange
1144 if (tp%rearrange)
then
1145 sr%Data => tp%rearranged_data
1147 sr%Data => tp%the_data
1156 call search(tp%root)
1158 if (sr%overflow)
then
1170 nfound, nalloc, results)
1179 integer(kind=intType),
intent(In) :: idxin, correltime, nalloc
1180 real(kind=
realtype),
intent(in) :: r2
1181 integer(kind=intType),
intent(out) :: nfound
1187 allocate (sr%qv(tp%dimen))
1188 sr%qv = tp%the_data(:, idxin)
1192 sr%centeridx = idxin
1193 sr%correltime = correltime
1195 sr%results => results
1198 sr%overflow = .false.
1200 call validate_query_storage(nalloc)
1206 sr%rearrange = tp%rearrange
1208 if (tp%rearrange)
then
1209 sr%Data => tp%rearranged_data
1211 sr%Data => tp%the_data
1213 sr%rearrange = tp%rearrange
1221 call search(tp%root)
1227 if (sr%overflow)
then
1228 write (*, *)
'KDTREE_TRANS: warning! return from kdtree2_r_nearest found more neighbors'
1229 write (*, *)
'KDTREE_TRANS: than storage was provided for. Answer is NOT smallest ball'
1230 write (*, *)
'KDTREE_TRANS: with that number of neighbors! I.e. it is wrong.'
1241 real(kind=
realtype),
target,
intent(In) :: qv(:)
1242 real(kind=
realtype),
intent(in) :: r2
1243 integer(kind=intType) :: nfound
1256 nullify (sr%results)
1261 sr%rearrange = tp%rearrange
1262 if (tp%rearrange)
then
1263 sr%Data => tp%rearranged_data
1265 sr%Data => tp%the_data
1273 sr%overflow = .false.
1275 call search(tp%root)
1289 integer(kind=intType),
intent(In) :: correltime, idxin
1290 real(kind=
realtype),
intent(in) :: r2
1291 integer(kind=intType) :: nfound
1297 allocate (sr%qv(tp%dimen))
1298 sr%qv = tp%the_data(:, idxin)
1303 sr%centeridx = idxin
1304 sr%correltime = correltime
1305 nullify (sr%results)
1311 sr%rearrange = tp%rearrange
1313 if (sr%rearrange)
then
1314 sr%Data => tp%rearranged_data
1316 sr%Data => tp%the_data
1324 sr%overflow = .false.
1326 call search(tp%root)
1333 subroutine validate_query_storage(n)
1338 integer(kind=intType),
intent(in) :: n
1340 if (
size(sr%results, 1) .lt. n)
then
1341 write (*, *)
'KDTREE_TRANS: you did not provide enough storage for results(1:n)'
1347 end subroutine validate_query_storage
1349 function square_distance(d, iv, qv)
result(res)
1358 integer(kind=intType) :: d
1361 real(kind=
realtype) :: iv(:), qv(:)
1364 res = sum((iv(1:d) - qv(1:d))**2)
1365 end function square_distance
1367 recursive subroutine search(node)
1378 type(
tree_node),
pointer :: ncloser, nfarther
1380 integer(kind=intType) :: cut_dim, i
1384 real(kind=
realtype),
pointer :: qv(:)
1387 if ((
associated(node%left) .and.
associated(node%right)) .eqv. .false.)
then
1389 if (sr%nn .eq. 0)
then
1390 call process_terminal_node_fixedball(node)
1392 call process_terminal_node(node)
1397 cut_dim = node%cut_dim
1400 if (qval < node%cut_val)
then
1401 ncloser => node%left
1402 nfarther => node%right
1403 dis = (node%cut_val_right - qval)**2
1406 ncloser => node%right
1407 nfarther => node%left
1408 dis = (node%cut_val_left - qval)**2
1412 if (
associated(ncloser))
call search(ncloser)
1415 if (
associated(nfarther))
then
1416 ballsize = sr%ballsize
1418 if (dis <= ballsize)
then
1427 if (i .ne. cut_dim)
then
1428 dis = dis + dis2_from_bnd(qv(i), box(i)%lower, box(i)%upper)
1429 if (dis > ballsize)
then
1438 call search(nfarther)
1442 end subroutine search
1444 real(kind=
realtype)
function dis2_from_bnd(x, amin, amax)
result(res)
1449 res = (x -
amax)**2;
1453 res = (
amin - x)**2;
1461 end function dis2_from_bnd
1463 logical function box_in_search_range(node, sr)
result(res)
1474 integer(kind=intType) :: dimen, i
1475 real(kind=
realtype) :: dis, ballsize
1479 ballsize = sr%ballsize
1483 l = node%box(i)%lower
1484 u = node%box(i)%upper
1485 dis = dis + (dis2_from_bnd(sr%qv(i), l, u))
1486 if (dis > ballsize)
then
1493 end function box_in_search_range
1495 subroutine process_terminal_node(node)
1503 real(kind=
realtype),
pointer :: qv(:)
1504 integer(kind=intType),
pointer :: ind(:)
1505 real(kind=
realtype),
pointer ::
data(:, :)
1507 integer(kind=intType) :: dimen, i, indexofi, k, centeridx, correltime
1508 real(kind=
realtype) :: ballsize, sd, newpri
1509 logical :: rearrange
1510 type(
pq),
pointer :: pqp
1521 ballsize = sr%ballsize
1522 rearrange = sr%rearrange
1524 data => sr%Data(1:, 1:)
1525 centeridx = sr%centeridx
1526 correltime = sr%correltime
1532 mainloop:
do i = node%l, node%u
1536 sd = sd + (
data(k, i) - qv(k))**2
1537 if (sd > ballsize) cycle mainloop
1544 sd = sd + (
data(k, indexofi) - qv(k))**2
1545 if (sd > ballsize) cycle mainloop
1549 if (centeridx > 0)
then
1550 if (abs(indexofi - centeridx) < correltime) cycle mainloop
1571 if (sr%nfound .lt. sr%nn)
then
1575 sr%nfound = sr%nfound + 1
1577 if (sr%nfound .eq. sr%nn) ballsize = newpri
1596 sr%ballsize = ballsize
1598 end subroutine process_terminal_node
1600 subroutine process_terminal_node_fixedball(node)
1609 real(kind=
realtype),
pointer :: qv(:)
1610 integer(kind=intType),
pointer :: ind(:)
1611 real(kind=
realtype),
pointer ::
data(:, :)
1613 integer(kind=intType) :: nfound
1614 integer(kind=intType) :: dimen, i, indexofi, k
1615 integer(kind=intType) :: centeridx, correltime, nn
1616 real(kind=
realtype) :: ballsize, sd
1617 logical :: rearrange
1624 ballsize = sr%ballsize
1625 rearrange = sr%rearrange
1627 data => sr%Data(1:, 1:)
1628 centeridx = sr%centeridx
1629 correltime = sr%correltime
1634 mainloop:
do i = node%l, node%u
1659 sd = sd + (
data(k, i) - qv(k))**2
1660 if (sd > ballsize) cycle mainloop
1667 sd = sd + (
data(k, indexofi) - qv(k))**2
1668 if (sd > ballsize) cycle mainloop
1672 if (centeridx > 0)
then
1673 if (abs(indexofi - centeridx) < correltime) cycle mainloop
1677 if (nfound .gt. sr%nalloc)
then
1680 sr%overflow = .true.
1682 sr%results(nfound)%dis = sd
1683 sr%results(nfound)%idx = indexofi
1690 end subroutine process_terminal_node_fixedball
1699 real(kind=
realtype),
intent(In) :: qv(:)
1700 integer(kind=intType),
intent(In) :: nn
1703 integer(kind=intType) :: i, j, k
1704 real(kind=
realtype),
allocatable :: all_distances(:)
1706 allocate (all_distances(tp%n))
1708 all_distances(i) = square_distance(tp%dimen, qv, tp%the_data(:, i))
1712 results(i)%dis = huge(1.0)
1716 if (all_distances(i) < results(nn)%dis)
then
1719 if (all_distances(i) < results(j)%dis)
exit
1722 do k = nn - 1, j, -1
1723 results(k + 1) = results(k)
1725 results(j)%dis = all_distances(i)
1729 deallocate (all_distances)
1739 real(kind=
realtype),
intent(In) :: qv(:)
1740 real(kind=
realtype),
intent(In) :: r2
1741 integer(kind=intType),
intent(out) :: nfound
1744 integer(kind=intType) :: i, nalloc
1745 real(kind=
realtype),
allocatable :: all_distances(:)
1747 allocate (all_distances(tp%n))
1749 all_distances(i) = square_distance(tp%dimen, qv, tp%the_data(:, i))
1753 nalloc =
size(results, 1)
1756 if (all_distances(i) < r2)
then
1758 if (nfound .lt. nalloc)
then
1760 results(nfound)%dis = all_distances(i)
1761 results(nfound)%idx = i
1765 deallocate (all_distances)
1775 integer(kind=intType),
intent(in) :: nfound
1783 if (nfound .gt. 1)
call heapsort_struct(results, nfound)
1788 subroutine heapsort(a, ind, n)
1795 integer(kind=intType),
intent(in) :: n
1796 real(kind=
realtype),
intent(inout) :: a(:)
1797 integer(kind=intType),
intent(inout) :: ind(:)
1802 integer(kind=intType) :: ivalue
1804 integer(kind=intType) :: i, j
1805 integer(kind=intType) :: ileft, iright
1815 if (n .eq. 1)
return
1820 value = a(ileft); ivalue = ind(ileft)
1822 value = a(iright); ivalue = ind(iright)
1823 a(iright) = a(1); ind(iright) = ind(1)
1825 if (iright == 1)
then
1826 a(1) =
value; ind(1) = ivalue
1832 do while (j <= iright)
1833 if (j < iright)
then
1834 if (a(j) < a(j + 1)) j = j + 1
1836 if (
value < a(j))
then
1837 a(i) = a(j); ind(i) = ind(j)
1844 a(i) =
value; ind(i) = ivalue
1846 end subroutine heapsort
1848 subroutine heapsort_struct(a, n)
1854 integer(kind=intType),
intent(in) :: n
1861 integer(kind=intType) :: i, j
1862 integer(kind=intType) :: ileft, iright
1872 if (n .eq. 1)
return
1882 if (iright == 1)
then
1889 do while (j <= iright)
1890 if (j < iright)
then
1891 if (a(j)%dis < a(j + 1)%dis) j = j + 1
1893 if (
value%dis < a(j)%dis)
then
1903 end subroutine heapsort_struct
real(kind=realtype), parameter one
integer(kind=inttype), parameter bucket_size
subroutine, public kdtree2_r_nearest_brute_force(tp, qv, r2, nfound, results)
subroutine, public kdtree2_sort_results(nfound, results)
subroutine, public kdtree2_n_nearest_brute_force(tp, qv, nn, results)
subroutine, public kdtree2_n_nearest_around_point(tp, idxin, correltime, nn, results)
integer(kind=inttype) function select_on_coordinate_value(v, ind, c, alpha, li, ui)
integer(kind=inttype) function, public kdtree2_r_count(tp, qv, r2)
type(kdtree2) function, pointer, public kdtree2_create(input_data, dim, sort, rearrange)
subroutine, public kdtree2_n_nearest(tp, qv, nn, results)
subroutine, public kdtree2destroy(tp)
subroutine, public kdtree2_r_nearest(tp, qv, r2, nfound, nalloc, results)
subroutine, public kdtree2_r_nearest_around_point(tp, idxin, correltime, r2, nfound, nalloc, results)
integer(kind=inttype) function, public kdtree2_r_count_around_point(tp, idxin, correltime, r2)
subroutine, public pq_extract_max(a, e)
subroutine, public pq_delete(a, i)
real(kind=realtype) function, public pq_insert(a, dis, idx)
subroutine, public pq_max(a, e)
real(kind=realtype) function, public pq_maxpri(a)
real(kind=realtype) function, public pq_replace_max(a, dis, idx)
type(pq) function, public pq_create(results_in)
integer, parameter realtype