PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/WPS/metgrid/src/minheap_module.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 207 lines | 145 code | 45 blank | 17 comment | 18 complexity | 618b32a8dd7613ee01ba23f6168ad394 MD5 | raw file
Possible License(s): AGPL-1.0
  1. ! Implements a heap using an array; top of the heap is the item
  2. ! with minimum key value
  3. module minheap_module
  4. use datatype_module
  5. use module_debug
  6. ! Maximum heap size -- maybe make this magically dynamic somehow?
  7. integer, parameter :: HEAPSIZE = 10000
  8. ! Type of item to be stored in the heap
  9. type heap_object
  10. type (data_node), pointer :: object
  11. end type heap_object
  12. ! The heap itself
  13. type (heap_object), allocatable, dimension(:) :: heap
  14. ! Index of last item in the heap
  15. integer :: end_of_heap
  16. contains
  17. ! Initialize the heap; current functionality can be had without
  18. ! the need for init function, but we may want more things later
  19. subroutine init_heap()
  20. implicit none
  21. end_of_heap = 0
  22. allocate(heap(HEAPSIZE))
  23. end subroutine init_heap
  24. subroutine heap_destroy()
  25. implicit none
  26. deallocate(heap)
  27. end subroutine heap_destroy
  28. subroutine add_to_heap(x)
  29. implicit none
  30. ! Arguments
  31. type (data_node), pointer :: x
  32. ! Local variables
  33. integer :: idx, parent
  34. call mprintf((end_of_heap == HEAPSIZE),ERROR, 'add_to_heap(): Maximum heap size exceeded')
  35. end_of_heap = end_of_heap + 1
  36. idx = end_of_heap
  37. heap(idx)%object => x
  38. heap(idx)%object%heap_index = idx
  39. do while (idx > 1)
  40. parent = floor(real(idx)/2.)
  41. if (heap(idx)%object%last_used < heap(parent)%object%last_used) then
  42. heap(idx)%object => heap(parent)%object
  43. heap(idx)%object%heap_index = idx
  44. heap(parent)%object => x
  45. heap(parent)%object%heap_index = parent
  46. idx = parent
  47. else
  48. idx = 1
  49. end if
  50. end do
  51. end subroutine add_to_heap
  52. subroutine remove_index(idx)
  53. implicit none
  54. ! Arguments
  55. integer, intent(in) :: idx
  56. ! Local variables
  57. integer :: indx, left, right
  58. type (data_node), pointer :: temp
  59. heap(idx)%object => heap(end_of_heap)%object
  60. heap(idx)%object%heap_index = idx
  61. end_of_heap = end_of_heap - 1
  62. indx = idx
  63. do while (indx <= end_of_heap)
  64. left = indx*2
  65. right = indx*2+1
  66. if (right <= end_of_heap) then
  67. if (heap(right)%object%last_used < heap(left)%object%last_used) then
  68. if (heap(right)%object%last_used < heap(indx)%object%last_used) then
  69. temp => heap(indx)%object
  70. heap(indx)%object => heap(right)%object
  71. heap(indx)%object%heap_index = indx
  72. heap(right)%object => temp
  73. heap(right)%object%heap_index = right
  74. indx = right
  75. else
  76. indx = end_of_heap + 1
  77. end if
  78. else
  79. if (heap(left)%object%last_used < heap(indx)%object%last_used) then
  80. temp => heap(indx)%object
  81. heap(indx)%object => heap(left)%object
  82. heap(indx)%object%heap_index = indx
  83. heap(left)%object => temp
  84. heap(left)%object%heap_index = left
  85. indx = left
  86. else
  87. indx = end_of_heap + 1
  88. end if
  89. end if
  90. else if (left <= end_of_heap) then
  91. if (heap(left)%object%last_used < heap(indx)%object%last_used) then
  92. temp => heap(indx)%object
  93. heap(indx)%object => heap(left)%object
  94. heap(indx)%object%heap_index = indx
  95. heap(left)%object => temp
  96. heap(left)%object%heap_index = left
  97. indx = left
  98. else
  99. indx = end_of_heap + 1
  100. end if
  101. else
  102. indx = end_of_heap + 1
  103. end if
  104. end do
  105. end subroutine remove_index
  106. subroutine get_min(x)
  107. implicit none
  108. ! Arguments
  109. type (data_node), pointer :: x
  110. ! Local variables
  111. integer :: idx, left, right
  112. type (data_node), pointer :: temp
  113. call mprintf((end_of_heap <= 0),ERROR, 'get_min(): No items left in the heap.')
  114. x => heap(1)%object
  115. heap(1)%object => heap(end_of_heap)%object
  116. heap(1)%object%heap_index = 1
  117. end_of_heap = end_of_heap - 1
  118. idx = 1
  119. do while (idx <= end_of_heap)
  120. left = idx*2
  121. right = idx*2+1
  122. if (right <= end_of_heap) then
  123. if (heap(right)%object%last_used < heap(left)%object%last_used) then
  124. if (heap(right)%object%last_used < heap(idx)%object%last_used) then
  125. temp => heap(idx)%object
  126. heap(idx)%object => heap(right)%object
  127. heap(idx)%object%heap_index = idx
  128. heap(right)%object => temp
  129. heap(right)%object%heap_index = right
  130. idx = right
  131. else
  132. idx = end_of_heap + 1
  133. end if
  134. else
  135. if (heap(left)%object%last_used < heap(idx)%object%last_used) then
  136. temp => heap(idx)%object
  137. heap(idx)%object => heap(left)%object
  138. heap(idx)%object%heap_index = idx
  139. heap(left)%object => temp
  140. heap(left)%object%heap_index = left
  141. idx = left
  142. else
  143. idx = end_of_heap + 1
  144. end if
  145. end if
  146. else if (left <= end_of_heap) then
  147. if (heap(left)%object%last_used < heap(idx)%object%last_used) then
  148. temp => heap(idx)%object
  149. heap(idx)%object => heap(left)%object
  150. heap(idx)%object%heap_index = idx
  151. heap(left)%object => temp
  152. heap(left)%object%heap_index = left
  153. idx = left
  154. else
  155. idx = end_of_heap + 1
  156. end if
  157. else
  158. idx = end_of_heap + 1
  159. end if
  160. end do
  161. end subroutine get_min
  162. end module minheap_module